Kubernetes快速入门

2、Kubernetes快速入门css

(1)Kubernetes集群的部署方法及部署要点html

 

(2)部署Kubernetes分布式集群node

 

(3)kubectl使用基础linux

一、简介nginx

kubectl就是API service的客户端程序,经过链接master节点上的API service实现k8s对象、资源的增删改查操做。git

对象:node、pod、service、controller(replicaset,deployment,statefulet,daemonset,job,cronjob)github

二、子命令web

分类redis

#基本命令算法

Basic Commands (Beginner:初级):
create :Create a resource from a file or from stdin.
expose :Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service
run :Run a particular image on the cluster
set :Set specific features on objects

 

Basic Commands (Intermediate:中级):
explain :Documentation of resources
get :Display one or many resources
edit :Edit a resource on the server
delete :Delete resources by filenames, stdin, resources and names, or by resources and label selector

 

Deploy Commands(部署命令):
rollout :Manage the rollout of a resource #回滚
scale :Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job #手动改变应用程序的规模
autoscale :Auto-scale a Deployment, ReplicaSet, or ReplicationController #自动改变

 

Cluster Management Commands(集群管理命令):
certificate :Modify certificate resources. #证书
cluster-info :Display cluster info #集群信息
top :Display Resource (CPU/Memory/Storage) usage.
cordon :Mark node as unschedulable #标记节点不可被调用
uncordon :Mark node as schedulable
drain :Drain node in preparation for maintenance #排干节点
taint :Update the taints on one or more nodes #给节点增长污点

 

Troubleshooting and Debugging Commands(故障排除和调试命令):
describe :Show details of a specific resource or group of resources #描述资源的详细信息
logs :Print the logs for a container in a pod
attach :Attach to a running container
exec :Execute a command in a container
port-forward :Forward one or more local ports to a pod #端口转发
proxy :Run a proxy to the Kubernetes API server
cp :Copy files and directories to and from containers.
auth :Inspect authorization

 

Advanced Commands(高级命令):
apply :Apply a configuration to a resource by filename or stdin
patch :Update field(s) of a resource using strategic merge patch
replace :Replace a resource by filename or stdin
wait :Experimental: Wait for a specific condition on one or many resources.
convert :Convert config files between different API versions

 

Settings Commands(设置命令):
label :Update the labels on a resource #标签,有长度限制
annotate :Update the annotations on a resource #注解
completion :Output shell completion code for the specified shell (bash or zsh) #命令补全

 

Other Commands:
alpha :Commands for features in alpha
api-resources :Print the supported API resources on the server
api-versions :Print the supported API versions on the server, in the form of "group/version"
config :Modify kubeconfig files
plugin :Provides utilities for interacting with plugins.
version :Print the client and server version information

 

Usage:
kubectl [flags] [options]

三、建立Pod

建立一个控制器名为nginx-deploy,镜像版本为nginx:1.14-alpine的Pod,暴露端口80,副本为1

[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1

以下图,此时能够看出建立成功了,并且在node02节点上,网段是10.244.2.0/24,而node01节点的网段是10.244.1.0/24。

可经过node01节点进行访问试试,而10.244.2.2是pod地址,只能在k8s集群中内部才能访问。

Pod的客户端有两类:其余Pod和集群外的客户端。

如今咱们把nginx-deploy-5b595999-2q6j5删除,而后控制器会自动建立一个新的Pod,以下图:

 

而此时Pod的ip为10.244.1.2,所以须要给Pod一个固定端点来进行访问,而这个固定端点是有servcie建立的

service的类型有:ClusterIP、NodePort、LoadBalancer、ExternalName。默认是ClusterIP,意思是这个service只有一个service IP,只能在集群内被各Pod客户端访问,而不能被集群外部的客户端访问。

建立service命令:kubectl expose deployment(控制器类型)nginx-deploy(控制器名称) --name 服务名 --port=service端口 --target-port=Pod的端口(即容器端口)

这样就能够经过固定的service的IP(10.98.39.54)来访问nginx了

不只能够经过访问service的ip来访问Pod,也能够经过service的服务名来访问,前提是Pod客户端须要能解析这个服务名,解析时须要依赖Core-dns服务。而物理机上的解析文件/etc/resolv.conf中的解析的IP不是Core-dns,能够经过master节点查看,命令为:kubectl get pods -n kube-system -o wide。以下图:

而coredns也有服务名,叫kube-dns,以下图:

若是从master节点上建立一个Pod客户端来访问其余Pod,它的dns服务直接指定到kube-dns的IP上。

所以在各个Pod客户端以外解析的时候要加上搜索域,例如,在clinet这个Pod以外的master节点上解析就须要加上搜索域:

此时能够将这个nginx的Pod删除,当控制器再次自动建立时,Pod的ip已经变为10.244.1.3,而后再次访问servic的ip和服务名均可以访问获得。

经过service的ip和服务名访问Pod,无论Pod是如何变化,它都是根据service的标签选择器来判断的

如何验证,咱们能够在master节点查看各Pod的标签选择器

 

同理,service的ip也动态生成的,当你删除service,再建立相同的service的话,ip已是另一个。

同理,Pod是根据标签选择器归为一类,而控制器,例如deployment也是根据标签选择器归为一类。

四、集群外部访问Pod

修改service中spec的type便可,将其改成NodePort

此时就能够在集群外部,经过节点ip:30020来访问Pod了。

(4)命令式应用部署、扩缩容、服务暴露

一、扩、缩容Pod

建立一类名为myapp的Pod,副本为2个,能够kubectl get deployment -w进行实时监控建立状况

 

同时也建立一个service,服务名为myapp

经过Pod客户端来访问进行验证,访问服务名myapp是能够看到Hell MyApp,而后也能够访问hostname.html查看Pod名称

经过循环语句来验证是随机访问这两个Pod的

在副本为2的基础上,进行扩容为5个

二、升级Pod

kubectl set image 控制器名称 Pod名 容器名=镜像:版本

注:容器名能够指多个,是指Pod内中的各层容器

将myapp版本更新为v2

kubectl set image deployment myapp myapp=ikubernetes/myapp:v2

经过rollout进行查看更新状态

 

三、回滚

3、资源配置清单及Pod资源

(1)Kubernetes API中的资源配置格式

 Restful定义:representational state transfer(表象性状态转变)或者表述性状态转移,详解见:https://blog.csdn.net/hzy38324/article/details/78360525?utm_source=gold_browser_extension

Restful中的状态get、put、delete、post经过kubectl run,get,edit等命令展示出来

(2)资源类型、API群组及其版本介绍

一、资源类型

k8s中全部内容抽象为资源,资源实例化后称为对象。

workload(工做负载):Pod,ReplicaSet,Deployment,StatefulSet,DaemonSet,Job,Cronjob等

服务发现及均衡:Service,Ingress等

配置与存储:Volume,CSI等

  ConfigMap,Secret

  DownwardAPI

集群级资源:Namespace,Node,Role,ClusterRole,RoleBinding,ClusterRoleBinding

元数据型资源:HPA,PodTemplate,LimitRange  

(3)Pod资源及其配置格式

一、yaml格式

 

# yaml格式的pod定义文件完整内容:
apiVersion: v1        #必选,api版本号(或者组名+版本号:group/version。而group省略,则表示core(核心组)的意思),例如v1就是核心组
kind: Pod       #必选,资源类别,例如:Pod
metadata:       #必选,元数据(内部须要嵌套二级、三级字段)
  name: string        #必选,Pod名称
  namespace: string     #必选,Pod所属的命名空间
  labels:       #自定义标签
    - name: string      #自定义标签名字
  annotations:        #自定义注释列表
    - name: string
spec:         #必选,规格即定义建立的资源对象应该要知足什么样的规范。Pod中容器的详细定义
  containers:       #必选,Pod中容器列表
  - name: string      #必选,容器名称
    image: string     #必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent]  #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,不然下载镜像,Nerver表示仅使用本地镜像
    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      #内存清楚,容器启动的初始可用数量
    livenessProbe:      #对Pod内个容器健康检查的设置,当探测无响应几回后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法便可
      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的重启策略,Always表示一旦无论以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示再也不重启该Pod
    nodeSelector: obeject   #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    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的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string   
        items:      
        - key: string
          path: string
      configMap:      #类型为configMap的存储卷,挂载预约义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string     

(4)使用配置清单建立自主式Pod资源

建立资源的方法:

  apiserver仅接收JSON格式的资源定义;

  yaml格式提供配置清单,apiserver可自动将其转为json格式,然后再提交;

命令:kubectl api-versions能够查看全部API 群组/版本

其中Pod是最核心资源所以属于核心组即v1,像控制器属于应用程序管理核心资源所以他们是apps组,即apps/v1。

大部分资源的配置清单格式都由5个一级字段组成:

apiVersion:api版本号

kind:资源类别

metadata:元数据

name:同一类别下的name是惟一的
        namespace:对应的对象属于哪一个名称空间
        labels:标签,每个资源均可以有标签,标签是一种键值数据
        annotations:资源注解
        
        每一个的资源引用方式(selflink):
            /api/GROUP/VERSION/namespace/NAMESPACE/TYPE/NAME

spec:用户定义一个资源对象应该所处的目标状态,也叫指望状态(可自定义)(disired state)

status:显示资源的当前状态(只读),本字段由kubernetes进行维护(current state)

 

 K8s存在内嵌的文档格式说明,可使用kubectl explain 进行查看,如查看Pod这个资源须要怎么定义:

[root@k8s-master ~]# kubectl explain pods
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>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata    <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

   spec    <Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

   status    <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

 

从上面能够看到apiVersion,kind等定义的键值都是<string>,而metadata和spec看到是一个<Object>,当看到存在<Object>的提示,说明该字段能够存在多个二级字段,那么可使用以下命令继续查看二级字段的定义方式:

[root@k8s-master ~]# kubectl explain pods.metadata
[root@k8s-master ~]# kubectl explain pods.spec

 

二级字段下,每一种字段都有对应的键值类型,经常使用类型大体以下:

<[]string>:表示是一个字串列表,也就是字串类型的数组

<Object>:表示是能够嵌套的字段

<map[string]string>:表示是一个由键值组成映射

<[]Object>:表示是一个对象列表

<[]Object> -required-:required表示该字段是一个必选的字段

 

使用配置清单建立自主式Pod资源 

[root@k8s-master ~]# mkdir mainfests
[root@k8s-master ~]# cd mainfrests
[root@k8s-master mainfrests]# vim pod-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name:myapp
    image: ikubernetes/myapp:v1
  - name: busybox
    image: busybox:latest
    command:
    - "/bin/sh"
    - "-c"
    - "sleep 3600"
[root@k8s-master mainfrests]# kubectl create -f pod-demo.yaml
[root@k8s-master mainfrests]# kubectl get pods
[root@k8s-master mainfrests]# kubectl describe pods pod-demo  #获取pod详细信息
[root@k8s-master mainfrests]# kubectl logs pod-demo myapp      #kubectl logs pod名称 容器名称 能够具体查看某个pod中某个容器的日志
[root@k8s-master mainfrests]# kubectl exec -it pod-demo  -c myapp -- /bin/sh
[root@k8s-master mainfrests]# kubectl delete -f xxxxx.yaml   #删除这个yaml文件建立的资源
使用yaml清单建立资源,能够建立裸控制器Pod,无控制器管理,一删除就没有了。

事实上使用kubectl命令管理资源有三种用法:

  • 命令式用法;
  • 命令式资源清单用法;
  • 声明式资源清单。使用声明式资源清单,能够确保资源尽量的向咱们声明的状态改变,并且能够随时改变声明,并随时应用。

Pod资源下spec的containers必需字段解析

自主式Pod资源(不受控制器控制)

[root@k8s-master ~]# kubectl explain pods.spec.containers

name    <string> -required-    #containers 的名字
image    <string>  #镜像地址
imagePullPolicy    <string>  #若是标签是latest,默认就是Always(老是下载镜像)  IfNotPresent(先看本地是否有此镜像,若是没有就下载) Never (就是使用本地镜像,若是没有就从不下载)
                 #这个字段是不容许被更改的
ports    <[]Object>  #是个对象列表;能够暴露多个端口;能够对每一个端口的属性定义 例如:(名称(可后期调用)、端口号、协议、暴露在的地址上) 暴露端口只是提供额外信息的,不能限制系统是否真的暴露

   - containerPort 容器端口

     hostIP  节点地址(基本不会使用)

     hostPort 节点端口

     name 名称

     protocol  (默认是TCP)
#修改镜像中的默认应用
args  <[]string>   传递参数给command 至关于docker中的CMD

command    <[]string> 至关于docker中的ENTRYPOINT;若是不提供命令,就运行镜像中的ENTRYPOINT。

官方文档对于command和args有个详细的介绍:

https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/

Description Docker field name Kubernetes field name
The command run by the container Entrypoint command
The arguments passed to the command Cmd args

表示docker中的entrypoint、cmd分别至关于kubernetes中的command和args。

若是Pod不提供commandargs使用Container,则使用Docker镜像中的cmd或者ENTRYPOINT。

若是Pod提供command但不提供args,则仅使用提供 command的。将忽略Docker镜像中定义EntryPoint和Cmd。

若是Pod中仅提供args,则args将做为参数提供给Docker镜像中EntryPoint。

若是提供了commandargs,则Docker镜像中的ENTRYPOINT和CMD都将不会生效,Pod中的args将做为参数给command运行

(5)标签及标签选择器

标签既能够在对象建立时指定,也能够在建立以后使用命令来管理

一、标签

key=value

  • key:只能使用字母、数字 、_ 、- 、. (只能以字母数字开头,不能超过63给字符)
  • value: 能够为空,只能使用字母、数字开头及结尾,中间可使用字母、数字 、_ 、- 、.(不能超过63给字符)
[root@k8s-master mainfests]# kubectl get pods --show-labels  #查看全部资源的pod标签
NAME       READY     STATUS    RESTARTS   AGE       LABELS
pod-demo   2/2       Running   0          25s       app=myapp,tier=frontend

[root@k8s-master mainfests]# kubectl get pods -l app  #只显示包含app的标签
NAME       READY     STATUS    RESTARTS   AGE
pod-demo   2/2       Running   0          1m
[root@k8s-master mainfests]# kubectl get pods -L app  #显示app字段的标签值的pod的资源
NAME       READY     STATUS    RESTARTS   AGE       APP
pod-demo   2/2       Running   0          1m        myapp

[root@k8s-master mainfests]# kubectl label pods pod-demo release=canary  #给pod-demo打上标签
pod/pod-demo labeled
[root@k8s-master mainfests]# kubectl get pods -l app --show-labels
NAME       READY     STATUS    RESTARTS   AGE       LABELS
pod-demo   2/2       Running   0          1m        app=myapp,release=canary,tier=frontend

[root@k8s-master mainfests]# kubectl label pods pod-demo release=stable --overwrite  #修改标签
pod/pod-demo labeled
[root@k8s-master mainfests]# kubectl get pods -l release
NAME       READY     STATUS    RESTARTS   AGE
pod-demo   2/2       Running   0          2m
[root@k8s-master mainfests]# kubectl get pods -l release,app
NAME       READY     STATUS    RESTARTS   AGE
pod-demo   2/2       Running   0          2m

二、标签选择器类别

  • 等值关系标签选择器:=, == , !=  (kubectl get pods -l app=test,app=dev)
  • 集合关系标签选择器: KEY in (value1,value2,value3);KEY notin (value1,value2,value3); !KEY (例如:kubectl get pods -l "app in (test,dev)")

许多资源支持内嵌字段定义其使用的标签选择器

  • matchLabels: 直接给定键值
  • matchExpressions: 基于给定的表达式来定义使用标签选择器,{key:"KEY",operator:"OPERATOR",values:[V1,V2,....]}
    • 操做符(即OPERATOR):in、notin(前两个Values字段的值必须为非空列表)、Exists、NotExists(后两个Values字段的值必须为空列表)

(6)Pod的节点选择器

 
 
[root@k8s-master mainfests]# kubectl get nodes --show-labels #查看node节点的标签
如上图beta.kubernetes.io是标签前缀,标签前缀必须是DNS名称,DNS域名或者子域名,最长长度不能超过254个字符
[root@k8s-master mainfests]# kubectl explain pod.spec
   nodeName    <string> #直接指定node节点名称
     NodeName is a request to schedule this pod onto a specific node. If it is
     non-empty, the scheduler simply schedules this pod onto that node, assuming
     that it fits resource requirements.

   nodeSelector    <map[string]string>
     NodeSelector is a selector which must be true for the pod to fit on a node.
     Selector which must match a node's labels for the pod to be scheduled on
     that node. More info:
     https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

 nodeSelector能够限定pod建立或者运行在哪一个或哪类节点上,举个例子,给节点k8s-node01打上标签disktype=ssd,让pod-demo指定建立在k8s-node01上

(1)给k8s-node01节点打标签
[root@k8s-master mainfests]# kubectl label nodes k8s-node01 disktype=ssd
node/k8s-node01 labeled

[root@k8s-master mainfests]# kubectl get nodes --show-labels
NAME         STATUS    ROLES     AGE       VERSION   LABELS
k8s-master   Ready     master    10d       v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=k8s-master,node-role.kubernetes.io/master=
k8s-node01   Ready     <none>    10d       v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=k8s-node01
k8s-node02   Ready     <none>    9d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=k8s-node02

(2)修改yaml文件,增长标签选择器
[root@k8s-master mainfests]# cat pod-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  - name: busybox
    image: busybox:latest
    command:
    - "/bin/sh"
    - "-c"
    - "sleep 3600"
  nodeSeletor:
    disktype: ssd

(3)从新建立pod-demo,能够看到固定调度在k8s-node01节点上
[root@k8s-master mainfests]# kubectl delete -f pod-demo.yaml 
pod "pod-demo" deleted

[root@k8s-master mainfests]# kubectl create -f pod-demo.yaml 
pod/pod-demo created
[root@k8s-master mainfests]# kubectl get pods -o wide
NAME       READY     STATUS    RESTARTS   AGE       IP            NODE
pod-demo   2/2       Running   0          20s       10.244.1.13   k8s-node01
[root@k8s-master mainfests]# kubectl describe pod pod-demo
......
Events:
  Type    Reason     Age   From                 Message
  ----    ------     ----  ----                 -------
  Normal  Scheduled  42s   default-scheduler    Successfully assigned default/pod-demo to k8s-node01
......

 

annotations:

 

  与label不一样的地方在于,annotations不能用于挑选资源对象,仅用于为对象提供"元数据",没有键值长度限制。在声明式配置构建大型镜像相关信息时,一般都会添加annotations,用来标记对应的资源对象的元数据或者属性信息,一样想查看annotations的信息可使用kubectl describe pod pod-demo

 

(7)容器存活状态探测及就绪状态探测

一、Pod生命周期

在pod生命周期中须要经历如下几个阶段。主容器(main container)在运行前须要作一些环境设定,所以在启动以前能够运行另外一个容器,为主容器作一些环境初始化,这类容器被称为init容器(init container)。初始化容器能够有多个,他们是串行执行的,执行完成后就退出了。在主容器刚刚启动以后,能够嵌入一个post start命令执行一些操做,在主容器结束前也能够指定一个 pre stop命令执行一些操做,做为开场的预设,结束时的清理。在整个主容器执行过程当中,还能够作两类对Pod的检测 liveness probe 和 readness probe。以下图:

Kubelet 能够选择是否执行在容器上运行的两种探针执行和作出反应:

  • livenessProbe:存活状态检测。指容器是否正在运行。若是存活探测失败,则 kubelet 会杀死容器,而且容器将受到其 重启策略 的影响。若是容器不提供存活探针,则默认状态为 Success
  • readinessProbe:就绪状态检测。指容器是否准备好服务请求。若是就绪探测失败,端点控制器将从与 Pod 匹配的全部 Service 的端点中删除该 Pod 的 IP 地址。初始延迟以前的就绪状态默认为 Failure。若是容器不提供就绪探针,则默认状态为 Success

二、常见的Pod状态

Pod 的 status 在信息保存在 PodStatus 中定义,其中有一个 phase 字段。

Pod 的相位(phase)是 Pod 在其生命周期中的简单宏观概述。该阶段并非对容器或 Pod 的综合汇总,也不是为了作为综合状态机。

Pod 相位的数量和含义是严格指定的。除了本文档中列举的状态外,不该该再假定 Pod 有其余的 phase值。

下面是 phase 可能的值:

  • 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像还没有建立。等待时间包括调度 Pod 的时间和经过网络下载镜像的时间,这可能须要花点时间。
  • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中全部的容器都已被建立。至少有一个容器正在运行,或者正处于启动或重启状态。
  • 成功(Succeeded):Pod 中的全部容器都被成功终止,而且不会再重启。
  • 失败(Failed):Pod 中的全部容器都已终止了,而且至少有一个容器是由于失败终止。也就是说,容器以非0状态退出或者被系统终止。
  • 未知(Unknown):由于某些缘由没法取得 Pod 的状态,一般是由于与 Pod 所在主机通讯失败。

下图是Pod的生命周期示意图,从图中能够看到Pod状态的变化。

三、总结

Pod生命周期中的重要行为

  一、初始化容器

  二、容器探测:livenessProbe和readinessProbe

    livenessProbe:存活状态检测(断定主容器是否处于运行状态)

    readinessProbe:就绪状态检测(断定容器中的主进程,是否已经准备就绪并能够对外提供服务)

  #kubernetes把容器探测分为这两种形式,而docker只需探测第一种,若是容器不存活,这个docker就结束了;相对于kubernetes而言,一个Pod里能够存在多个容器。

容器探测的三种行为:

  • ExecAction:在容器内执行指定命令。若是命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。若是端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。若是响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

容器重启策略

[root@k8s-master mainfests]# kubectl explain pod.spec

 

  Spec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always。

    Always:一旦Pod中的容器挂了,老是重启

    OnFailure:状态错误时才重启,正常关掉不重启

    Never: 状态错误和正常关掉也从不重启

  其中默认值是Always,若是一直重启对服务器是有压力的,因此它重启策略是,第一次为当即重启;接下来第二次重启则须要延时,好比延时10s在进行重启;第三次延时20s;第四次延时40s;往下80s、160s、300s,300s是最长的延时时间(即5分钟)。pod一旦绑定到一个节点,Pod 将永远不会从新绑定到另外一个节点,除非删除Pod从新建立。

四、livenessProbe解析

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

KIND:     Pod
VERSION:  v1

RESOURCE: livenessProbe <Object>

exec  #command 的方式探测。例如:ps一个进程

failureThreshold #探测几回失败才算失败,默认是连续三次

periodSeconds #每次多长时间探测一次,默认10s

timeoutSeconds #探测超时的秒数 默认1s

initialDelaySeconds  #初始化延迟探测。第一次探测的时候延迟探测,由于主程序未必启动完成

tcpSocket #检测端口的探测

httpGet #http请求探测

 

举个例子:定义一个liveness的pod资源类型,基础镜像为busybox,在busybox这个容器启动后会执行建立/tmp/test的文件啊,并删除,而后等待3600秒。随后定义了存活性探测,方式是以exec的方式执行命令判断/tmp/test是否存在,存在即表示存活,不存在则表示容器已经挂了。

[root@master manifests]# cat liveness.exec.ymal 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox:latest
    imagePullPolicy: IfNotPresent #若是存在就不要下载了
    command: ["/bin/sh","-c","touch /tmp/healthy;sleep 60;rm -f /tmp/healthy;sleep 3600"]
    livenessProbe: #存活性探测
      exec: 
        command: ["test","-e","/tmp/healthy"] #-e表示探测文件是否存在
      initialDelaySeconds: 1 #表示容器启动后多长时间开始探测
      periodSeconds: 3 #表示每隔3s钟探测一次

 

[root@master manifests]# kubectl create -f liveness.exec.ymal 
pod/liveness-exec-pod created

 

[root@master manifests]# kubectl get pods -w
NAME                          READY     STATUS             RESTARTS   AGE
liveness-exec-pod             1/1       Running            2          4m

 

[root@master manifests]# kubectl get pods -w
NAME                          READY     STATUS             RESTARTS   AGE
liveness-exec-pod             1/1       Running            4          6m

 

[root@master manifests]# kubectl get pods -w
NAME                          READY     STATUS             RESTARTS   AGE
client                        1/1       Running            0          3d
liveness-exec-pod             1/1       Running            5          9m

 

[root@master manifests]#  kubectl get pods -w
NAME                          READY     STATUS             RESTARTS   AGE
client                        1/1       Running            0          3d
liveness-exec-pod             1/1       Running            9          23m

 

能够看到restart此时在随着时间增加。 

上面的例子是用exec执行命令进行探测的。 

下面咱们看看基于tcp和httpget探测的选项。

[root@master manifests]kubectl explain pods.spec.containers.livenessProbe.tcpSocket

[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe.httpGet

 

下面举个例子

[root@master manifests]# cat liveness.httpget.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent #若是存在就不要下载了
    ports:
    - name: http
      containerPort: 80
    livenessProbe: #存活性探测
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3 #表示每隔3s钟探测一次

 

[root@master manifests]# kubectl  create -f liveness.httpget.yaml

[root@master manifests]# kubectl get pods NAME READY STATUS RESTARTS AGE liveness-httpget-pod 1/1 Running 0 4m
[root@master manifests]# kubectl exec -it liveness-httpget-pod -- /bin/sh # rm -rf /usr/share/nginx/html/index.html
[root@master manifests]# kubectl get pods NAME READY STATUS RESTARTS AGE liveness-httpget-pod 1/1 Running 1 27m

 

上面能够看到,当删除pod里面的/usr/share/nginx/html/index.html,liveness监测到index.html文件被删除了,因此restarts次数为1,可是只重启一次,不会再重启了。这是由于重启一次后,nginx容器就从新初始化了,里面就会又生成index.html文件。因此里面就会有新的index.html文件了。 

readlinessProbe(准备就绪型探针) 

[root@master manifests]# cat  readiness-httpget.ymal 
apiVersion: v1
kind: Pod
metadata:
  name: readdliness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readliness-httpget-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent #若是存在就不要下载了
    ports:
    - name: http
      containerPort: 80
    readinessProbe: #准备型探针
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3 #表示每隔3s钟探测一次

 

[root@master manifests]# kubectl create -f readiness-httpget.ymal 
pod/readdliness-httpget-pod created

[root@master ~]# kubectl get pods
NAME                          READY     STATUS             RESTARTS   AGE
readdliness-httpget-pod       1/1       Running            0          16h

[root@master ~]# kubectl exec -it readdliness-httpget-pod -- /bin/sh
# rm -rf /usr/share/nginx/html/index.html

[root@master ~]# kubectl get pods
NAME                          READY     STATUS             RESTARTS   AGE
readdliness-httpget-pod       0/1       Running            0          16h

 

 上面能够看到,ready变成0/1了,可是status是runing的,这就是说nginx进程是在的,只是index.html不见了,能够断定nginx没有就绪。

postStart(启动后钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.postStart

 

 postStart是指容器在启动以后当即执行的操做,若是执行操做失败了,容器将被终止而且重启。而重启与否是由重启策略。

[root@master manifests]# cat poststart-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: poststart-pod
  namespace: default
spec:
  containers:
  - name: busybox-httpd
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    lifecycle: #生命周期事件
      postStart:
        exec:
          command: ["mkdir", "-p","/data/web/html"] #这个command是定义postStart后的须要执行的命令
    command: ["/bin/sh","-c","sleep 3600"] #这是定义容器里面执行的命令,不过这个命令要先于postStart里面的command
    #args: ["-f","-h /data/web/html"]  #-f是前台,-h是家目录

 

[root@master manifests]# kubectl create -f poststart-pod.yaml 
pod/posttart-pod created

 

说明:删除的方法

[root@master manifests]# kubectl delete -f poststart-pod.yaml 
pod "posttart-pod" deleted

[root@master manifests]# kubectl get pods
NAME                          READY     STATUS             RESTARTS   AGE
poststart-pod                 1/1       Running            0          3m

[root@master manifests]#  kubectl exec -it poststart-pod -- /bin/sh
/ # ls /data
web
/ # ls /data/web/html/

 

上面看到在容器启动后,创建了/data/web/html目录。这就是postStart的用法。

preStop(终止以前钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.preStop

 

preStop是指容器在终止前要当即执行的命令,等这些命令执行完了,容器才能终止。

容器的重启策略-restartPolicy

   一旦pod中的容器挂了,咱们就把容器重启。

    策略包括以下:

    Always:表示容器挂了老是重启,这是默认策略 

    OnFailures:表容器状态为错误时才重启,也就是容器正常终止时才重启 

    Never:表示容器挂了不予重启 

    对于Always这种策略,容器只要挂了,就会当即重启,这样是很耗费资源的。因此Always重启策略是这么作的:第一次容器挂了当即重启,若是再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推 

 容器的终止策略

    k8s会给容器30s的时间进行终止,若是30s后还没终止,就会强制终止。 

  总结

pod:
        apiVersion
        kind
        metadata
        spec
        status(只读)
        spec:
                containers
                nodeSelector
                nodeName
                restartPolicy: Always,Never,OnFailure
                containers:
                        name
                        image
                        imagePullPolicy: Always、Never、IfNotPresent
                        ports:
                                name
                                containerPort
                        livenessProbe
                        readinessProbe
                        liftcycle
                ExecAction: exec
                TCPSocketAction: tcpSocket
                HTTPGetAction: httpGet

 

4、Pod控制器

(1)Pod控制器及其功用

(2)经过配置清单管理ReplicaSet控制器,包括扩缩容及更新机制

(3)Deployment控制器基础应用及滚动更新:灰度部署、金丝雀部署、蓝绿部署的实现;

(4)DaemonSet控制器基础应用及使用案例

 

 

 上一节,咱们建立的pod,是经过资源配置清单定义的,若是手工把这样的pod删除后,不会本身从新建立,这样建立的pod叫自主式Pod。 

 

    在生产中,咱们不多使用自主式pod。 

 

    下面咱们学习另一种pod,叫控制器管理的Pod,控制器会按照定义的策略严格控制pod的数量,一旦发现pod数量少了,会当即自动创建出来新的pod;一旦发现pod多了,也会自动杀死多余的Pod。 

 

    pod控制器:ReplicaSet控制器、Deployment控制器(必须掌握)、DaenibSet控制器、Job控制器

 

     ReplicaSet控制器 :替用户建立指定数量Pod的副本,并保证pod副本知足用户指望的数量;并且更新自动扩缩容机制。

  replicat主要由三个组件组成:一、用户指望的pod副本数量;二、标签选择器(控制管理pod副本);三、pod资源模板(若是pod数量少于指望的,就根据pod模板来新建必定数量的pod)。 

 

     Deployment控制器 :Deployment经过控制replicaset来控制Pod。用于管理无状态应用,目前来讲最好的控制器。Deployment支持滚动更新和回滚,声明式配置的功能。Deployment只关注群体,而不关注个体。

     DaemonSet控制器 :用于确保集群中的每个节点只运行一个特定的pod副本(画外音,若是没有DaemonSet,一个节点能够运行多个pod副本)。若是在集群中新加一个节点,那么这个新节点也会自动生成一个Pod副本。

                   特性:服务是无状态的;服务必须是守护进程

     Job控制器 :对于那些 只作一次,只要完成就正常退出,没完成才重构pod  ,叫job控制器。 

 

    Cronjob:周期性任务控制,不须要持续后台运行

    

    StatefulSet控制器: 管理有状态应用,每个pod副本都是被单独管理的。它拥有着本身独有的标识。 

 

    K8s在1.2+至1.7开始,支持TPR(third party resources 第三方资源)。在k8s 1.8+之后,支持CDR(Custom Defined Reources,用户自定义资源)。

  Operator是CoreOS推出的旨在简化复杂有状态应用管理的框架,它是一个感知应用状态的控制器,经过扩展Kubernetes API来自动建立、管理和配置应用实例。 

 ReplicaSet控制器

ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即若是有容器异常退出,会自动建立新的Pod来替代;而若是异常多出来的容器也会自动回收。

在新版本的Kubernetes中建议使用ReplicaSet来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不一样,只是名字不同,而且ReplicaSet支持集合式的selector。

虽然ReplicaSet能够独立使用,但通常仍是建议使用 Deployment 来自动管理ReplicaSet,这样就无需担忧跟其余机制的不兼容问题(好比ReplicaSet不支持rolling-update但Deployment支持)。

[root@master manifests]# kubectl explain replicaset
[root@master manifests]# kubectl explain  rs (replicaset的简写)
[root@master manifests]# kubectl explain rs.spec.template

 

[root@master manifests]# kubectl get deploy
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
myapp          2         2         2            0           10d
mytomcat       3         3         3            3           10d
nginx-deploy   1         1         1            1           13d
[root@master manifests]# kubectl delete deploy myapp 
deployment.extensions "myapp" deleted
[root@master manifests]# kubectl delete deploy nginx-deploy
deployment.extensions "nginx-deploy" deleted

 

[root@master manifests]# cat rs-demo.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp
  namespace: default
spec: #这是控制器的spec
  replicas: 2 #几个副本
  selector:   #查看帮助:,标签选择器。 kubectl explain rs.spec.selector
    matchLabels:
      app: myapp
      release: canary
  template:  # 查看帮助:模板 kubectl explain rs.spec.template
    metadata: # kubectl explain rs.spec.template.metadata
      name: myapp-pod
      labels:  #必须符合上面定义的标签选择器selector里面的内容
        app: myapp
        release: canary
        environment: qa
    spec: #这是pod的spec
      containers:
      - name: myapp-container
        image: ikubernetes/nginx:latest
        ports: 
        - name: http
          containerPort: 80

 

[root@master manifests]# kubectl create -f rs-demo.yaml 
replicaset.apps/myapp created

 

[root@master manifests]# kubectl get rs
NAME                 DESIRED   CURRENT   READY     AGE
myapp                2         2         2         3m

 

看到上面的ready是2,表示两个replcatset控制器都在正常运行。 

[root@master manifests]# kubectl get pods --show-labels
myapp-6kncv                1/1       Running            0          15m       app=myapp,environment=qa,release=canary
myapp-rbqjz                1/1       Running            0          15m       app=myapp,environment=qa,release=canary         5m
pod-demo                   0/2       CrashLoopBackOff   2552       9d        app=myapp,tier=frontend

 

[root@master manifests]# kubectl describe pods myapp-6kncv 
IP:                 10.244.2.44

 

[root@master manifests]# curl  10.244.2.44
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

 

编辑replicatset的配置文件(这个文件不是咱们手工建立的,而是apiserver维护的)

[root@master manifests]# kubectl edit rs myapp

 

 把里面的replicas改为5,保存后就当即生效。

[root@master manifests]#  kubectl get pods --show-labels
NAME                       READY     STATUS              RESTARTS   AGE       LABELS
client                     0/1       Error               0          11d       run=client
liveness-httpget-pod       1/1       Running             3          5d        <none>
myapp-6kncv                1/1       Running             0          31m       app=myapp,environment=qa,release=canary
myapp-c64mb                1/1       Running             0          3s        app=myapp,environment=qa,release=canary
myapp-fsrsg                1/1       Running             0          3s        app=myapp,environment=qa,release=canary
myapp-ljczj                0/1       ContainerCreating   0          3s        app=myapp,environment=qa,release=canary
myapp-rbqjz                1/1       Running             0          31m       app=myapp,environment=qa,release=canary

 

一样,也能够用命令kubectl edit rs myapp升级版本,改里面的image: ikubernetes/myapp:v2,这样就变成v2版本了。

[root@master manifests]# kubectl get rs -o wide
NAME                 DESIRED   CURRENT   READY     AGE       CONTAINERS        IMAGES                 SELECTOR
myapp                5         5         5         1h        myapp-container   ikubernetes/myapp:v2   app=myapp,release=canary

 

不过,只有pod重建后,好比增长、删除Pod,才会更新成v2版本。 

Deployment控制器

    咱们能够经过Deployment控制器来动态更新pod的版本。 

    咱们先创建replicatset v2版本,而后一个一个的删除replicatset v1版本中的Pod,这样自动新建立的pod就会变成v2版本了。当pod所有变成v2版本后,replicatset v1并不会删除,这样一旦发现v2版本有问题,还能够回退到v1版本。

    一般deployment默认保留10版本的replicatset。 

[root@master manifests]# kubectl explain deploy
[root@master manifests]# kubectl explain deploy.spec
[root@master manifests]# kubectl explain deploy.spec.strategy (更新策略)
[root@master ~]# kubectl delete rs myapp

 

[root@master manifests]# cat deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector: #标签选择器
    matchLabels: #匹配的标签为
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp #和上面的myapp要匹配
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

 

[root@master manifests]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-deploy created

 

   apply表示是声明式更新和建立。 

[root@master manifests]# kubectl get deploy
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
myapp-deploy   2         2         2            2           1m

 

[root@master ~]# kubectl get rs
NAME                      DESIRED   CURRENT   READY     AGE
myapp-deploy-69b47bc96d   2         2         2         17m

 

  上面的rs式deployment自动建立的。 

[root@master ~]# kubectl get pods
NAME                            READY     STATUS    RESTARTS   AGE
myapp-deploy-69b47bc96d-7jnwx   1/1       Running   0          19m
myapp-deploy-69b47bc96d-btskk   1/1       Running   0          19m

 

修改配置文件deploy-demo.yaml,把replicas数字改为3,而后再执行kubectl apply -f deploy-demo.yaml 便可使配置文件里面的内容生效。

[root@master ~]# kubectl describe deploy myapp-deploy

[root@master ~]# kubectl get pods -l app=myapp -w

 

  -l使标签过滤 

 -w是动态监控

[root@master ~]# kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-69b47bc96d   2         2         2         1h        myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=2560367528,release=canary

 

看滚动更新的历史:

[root@master ~]# kubectl rollout history deployment myapp-deploy
deployments "myapp-deploy"
REVISION  CHANGE-CAUSE
1         <none>

 

  下面咱们把deployment改为5个:咱们可使用vim  deploy-demo.yaml方法,把里面的replicas改为5。固然,还可使用另一种方法,就patch方法,举例以下。

[root@master manifests]# kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}'
deployment.extensions/myapp-deploy patched


[root@master manifests]# kubectl get deploy NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE myapp-deploy 5 5 5 5 2h
[root@master manifests]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp-deploy-69b47bc96d-7jnwx 1/1 Running 0 2h myapp-deploy-69b47bc96d-8gn7v 1/1 Running 0 59s myapp-deploy-69b47bc96d-btskk 1/1 Running 0 2h myapp-deploy-69b47bc96d-p5hpd 1/1 Running 0 59s myapp-deploy-69b47bc96d-zjv4p 1/1 Running 0 59s mytomcat-5f8c6fdcb-9krxn 1/1 Running 0 8h

 

下面修改策略: 

[root@master manifests]# kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavaliable":0}}}}'
deployment.extensions/myapp-deploy patched

 

strategy:表示策略

maxSurge:表示最多几个控制器存在

maxUnavaliable:表示最多有几个控制器不可用

[root@master manifests]# kubectl describe deployment myapp-deploy
RollingUpdateStrategy: 0 max unavailable, 1 max surge

 

下面咱们用set image命令,将镜像myapp升级为v3版本,而且将myapp-deploy控制器标记为暂停。被pause命令暂停的资源不会被控制器协调使用,可使“kubectl rollout resume”命令恢复已暂停资源。

[root@master manifests]# kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 &&
kubectl rollout pause deployment myapp-deploy

[root@master ~]# kubectl get pods -l app=myapp -w

 

中止暂停:

[root@master ~]# kubectl rollout resume deployment myapp-deploy
deployment.extensions/myapp-deploy resumed

 

看到继续更新了(即删一个更新一个,删一个更新一个):

[root@master manifests]# kubectl rollout status deployment myapp-deploy
Waiting for deployment "myapp-deploy" rollout to finish: 2 out of 5 new replicas have been updated...
Waiting for deployment spec update to be observed...
Waiting for deployment spec update to be observed...
Waiting for deployment "myapp-deploy" rollout to finish: 2 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 4 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 4 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 4 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "myapp-deploy" rollout to finish: 1 old replicas are pending termination...
deployment "myapp-deploy" successfully rolled out

 

[root@master manifests]# kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-69b47bc96d   0         0         0         6h        myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=2560367528,release=canary
myapp-deploy-6bdcd6755d   5         5         5         3h        myapp        ikubernetes/myapp:v3   app=myapp,pod-template-hash=2687823118,release=canary
mytomcat-5f8c6fdcb        3         3         3         12h       mytomcat     tomcat                 pod-template-hash=194729876,run=mytomcat

 

上面能够看到myapp有v1和v3两个版本。 

[root@master manifests]# kubectl rollout history deployment myapp-deploy
deployments "myapp-deploy"
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

 

上面能够看到有两个历史更新记录。 

下面咱们把v3回退到上一个版本(不指定就是上一个版本)。

[root@master manifests]# kubectl  rollout undo deployment myapp-deploy --to-revision=1
deployment.extensions/myapp-deploy

 

能够看到初版还原成第3版了: 

[root@master manifests]# kubectl rollout history deployment myapp-deploy
deployments "myapp-deploy"
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

 

 能够看到正在工做的是v1版,即回退到了v1版。 

[root@master manifests]# kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-69b47bc96d   5         5         5         6h        myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=2560367528,release=canary
myapp-deploy-6bdcd6755d   0         0         0         3h        myapp        ikubernetes/myapp:v3   app=myapp,pod-template-hash=2687823118,release=canary

 

DaemonSet控制器 

 经过 https://hub.docker.com/r/ikubernetes/filebeat/tags/能够看到filebeat的版本有哪些:

[root@node1 manifests]# docker pull ikubernetes/filebeat:5.6.5-alpine
[root@node2 manifests]# docker pull ikubernetes/filebeat:5.6.5-alpine

 

node1和node2上都下载filebeat镜像。 

[root@node1 ~]# docker image inspect ikubernetes/filebeat:5.6.5-alpine

[root@master manifests]# kubectl explain pods.spec.containers.env

 

[root@master manifests]# cat ds-demo.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: myapp-ds
  namespace: default
spec:
  selector: #标签选择器
    matchLabels: #匹配的标签为
      app: filebeat
      release: stable
  template:
    metadata:
      labels:
        app: filebeat #和上面的myapp要匹配
        release: stable
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        env:
        - name: REDIS_HOST
          value: redis.default.svc.cluster.local #随便取的名字
          name: REDIS_LOG_LEVEL
          value: info

 

[root@master manifests]# kubectl apply -f ds-demo.yaml 
daemonset.apps/myapp-ds created

 

看到myapp-ds已经运行起来了,而且是两个myapp-ds,这是由于咱们有两个Node节点。另外master节点上是不会运行myapp-ds控制器的,由于master有污点(除非你设置容许有污点,才能够在master上容许myapp-ds)

[root@master manifests]# kubectl get pods
NAME                            READY     STATUS    RESTARTS   AGE
myapp-ds-5tmdd                  1/1       Running   0          1m
myapp-ds-dkmjj                  1/1       Running   0          1m

 

[root@master ~]# kubectl logs  myapp-ds-dkmjj

[root@master manifests]# kubectl delete -f ds-demo.yaml

 

[root@master manifests]# cat ds-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      role: logstor #日志存储角色
  template:
    metadata:
      labels:
        app: redis
        role: logstor
    spec: #这个是容器的spec
      containers:
      - name: redis
        image: redis:4.0-alpine
        ports:
        - name: redis
          containerPort: 6379
#用减号隔离资源定义清单
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat-ds
  namespace: default
spec:
  selector: #标签选择器
    matchLabels: #匹配的标签为
      app: filebeat
      release: stable
  template:
    metadata:
      labels:
        app: filebeat #和上面的myapp要匹配
        release: stable
    spec:
      containers:
      - name: filebeat
        image: ikubernetes/filebeat:5.6.6-alpine
        env:
        - name: REDIS_HOST #这是环境变量名,value是它的值
          value: redis.default.svc.cluster.local #随便取的名字
        - name: REDIS_LOG_LEVEL
          value: info

 

[root@master manifests]# kubectl create -f ds-demo.yaml 
deployment.apps/redis created
daemonset.apps/filebeat-ds created

 

[root@master manifests]# kubectl expose deployment redis --port=6379 ##这是在用expose方式建立service,其实还有一种方式是根据清单建立service
service/redis exposed

 

[root@master manifests]# kubectl get svc  #service的简称
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
redis        ClusterIP   10.106.138.181   <none>        6379/TCP       48s

 

[root@master manifests]# kubectl get pods
NAME                            READY     STATUS    RESTARTS   AGE
filebeat-ds-hgbhr               1/1       Running   0          9h
filebeat-ds-xc7v7               1/1       Running   0          9h
redis-5b5d6fbbbd-khws2          1/1       Running   0          33m

 

[root@master manifests]# kubectl exec -it redis-5b5d6fbbbd-khws2 -- /bin/sh
/data # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      
tcp        0      0 :::6379                 :::*                    LISTEN   
/data # nslookup redis.default.svc.cluster.local  #看到DNS能够解析出来ip
nslookup: can't resolve '(null)': Name does not resolve
Name:      redis.default.svc.cluster.local
Address 1: 10.106.138.181 redis.default.svc.cluster.local 
/data # redis-cli -h redis.default.svc.cluster.local
redis.default.svc.cluster.local:6379> keys *
(empty list or set)
redis.default.svc.cluster.local:6379>

 

[root@master manifests]# kubectl exec -it filebeat-ds-pnk8b -- /bin/sh
/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /usr/local/bin/filebeat -e -c /etc/filebeat/filebeat.yml
   15 root       0:00 /bin/sh
   22 root       0:00 ps aux
   
/ # cat  /etc/filebeat/filebeat.yml
filebeat.registry_file: /var/log/containers/filebeat_registry
filebeat.idle_timeout: 5s
filebeat.spool_size: 2048
logging.level: info
filebeat.prospectors:
- input_type: log
  paths:
    - "/var/log/containers/*.log"
    - "/var/log/docker/containers/*.log"
    - "/var/log/startupscript.log"
    - "/var/log/kubelet.log"
    - "/var/log/kube-proxy.log"
    - "/var/log/kube-apiserver.log"
    - "/var/log/kube-controller-manager.log"
    - "/var/log/kube-scheduler.log"
    - "/var/log/rescheduler.log"
    - "/var/log/glbc.log"
    - "/var/log/cluster-autoscaler.log"
  symlinks: true
  json.message_key: log
  json.keys_under_root: true
  json.add_error_key: true
  multiline.pattern: '^\s'
  multiline.match: after
  document_type: kube-logs
  tail_files: true
  fields_under_root: true
output.redis:
  hosts: ${REDIS_HOST:?No Redis host configured. Use env var REDIS_HOST to set host.}
  key: "filebeat"
   
  
  
/ # printenv
REDIS_HOST=redis.default.svc.cluster.local
/ # nslookup redis.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve
Name:      redis.default.svc.cluster.local
Address 1: 10.106.138.181 redis.default.svc.cluster.local

 

 daemon-set也支持滚动更新。 

[root@master manifests]# kubectl set image daemonsets filebeat-ds filebeat=ikubernetes/filebeat:5.5.7-alpine

 

说明: daemonsets filebeat-ds表示daemonsets名字叫filebeat-ds;

           filebeat=ikubernetes/filebeat:5.5.7-alpine表示filebeat容器=ikubernetes/filebeat:5.5.7-alpine

5、Service资源对象

(1)Service及其实现模型

(2)Service的类型及其功用

(3)Service类型的建立及应用方式

(4)Headless Service

(5)基于DNS的服务发现简介

(6)Ingress类型及实现方式

 

 Ingress:就是能利用 Nginx(不经常使用)、Haproxy(不经常使用)、Traefik(经常使用)、Envoy(经常使用) 啥的负载均衡器暴露集群内服务的工具。

 

     Ingress为您提供七层负载均衡能力,您能够经过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。做为集群流量接入层,Ingress 的高可靠性显得尤其重要。

 

    小知识:咱们把k8s里面的pod服务发布到集群外部,能够用ingress,也能够用NodePort。 

 

 

    externalLB:外部的负载均衡器 

 

    service site:只是用来给pod分组归类的。 

 

1
[root@master manifests]# kubectl explain ingress

 

    建立名称空间: 

 

1
2
3
4
5
6
7
8
[root@master manifests]# kubectl create namespace ingress-nginx
namespace/dev created
[root@master manifests]# kubectl get ns
NAME          STATUS    AGE
default        Active     17 d
ingress-nginx   Active     8 s
kube-public   Active     17 d
kube-system   Active     17 d

 

    访问 https://github.com/kubernetes/ingress-nginx,进入deploy目录,里面就有咱们要用的yaml文件。

 

1
2
3
4
5
6
7
8
  各文件的做用:
configmap.yaml:提供configmap能够在线更行nginx的配置
default-backend.yaml:提供一个缺省的后台错误页面  404
namespace.yaml:建立一个独立的命名空间 ingress-nginx
rbac.yaml:建立对应的role rolebinding 用于rbac
tcp-services-configmap.yaml:修改L 4 负载均衡配置的configmap
udp-services-configmap.yaml:修改L 4 负载均衡配置的configmap
with-rbac.yaml:有应用rbac的nginx-ingress-controller组件

 

    访问https://kubernetes.github.io/ingress-nginx/deploy/#generice-deployment,里面是ingress的部署文档

 

1
2
[root@master ~]# mkdir  ingress-nginx
[root@master ~]# cd ingress-nginx

 

 部署ingress方法一(分步部署):

 

    下载以下配置文件: 

 

1
[root@master ingress-nginx]# for file in namespace.yaml configmap.yaml rbac.yaml tcp-services-configmap.yaml with-rbac.yaml udp-services-configmap.yaml; do wget  https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/$file; done

 

 

1
2
[root@master ingress-nginx]# ls
configmap.yaml  namespace.yaml  rbac.yaml  tcp-services-configmap.yaml  udp-services-configmap.yaml  with-rbac.yaml

 

一、建立名称空间: 

 

1
2
[root@master ingress-nginx]# kubectl apply -f namespace.yaml 
namespace/ingress-nginx configured

 

二、把剩下的ymal文件全应用

 

1
2
3
4
5
6
7
8
9
10
11
[root@master ingress-nginx]# kubectl  apply -f ./
configmap/nginx-configuration created
namespace/ingress-nginx configured
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k 8 s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k 8 s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k 8 s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k 8 s.io/nginx-ingress-clusterrole-nisa-binding created
configmap/tcp-services created
configmap/udp-services created
deployment.extensions/nginx-ingress-controller created

 

1
2
3
4
[root@master ingress-nginx]# kubectl get pods -n ingress-nginx -w
NAME                                        READY     STATUS              RESTARTS   AGE
default-http-backend -6586 bc 58 b 6 -qd 9 fk        0 / 1        running     0           4 m
nginx-ingress-controller -6 bd 7 c 597 cb-zcbbz    0 / 1        running    0           1 m

 

    能够看到ingress-nginx名称空间里面有两个pod都处于running状态 

 

部署ingress方法二(一键部署): 

 

只下载mandatory.yaml文件,由于这个文件里面包含了上面全部yaml文件里面的内容。这是一键部署。

 

1
2
[root@master ingress-nginx]# wget 
https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

 

1
[root@master ingress-nginx]#kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

 

1
2
3
4
[root@master ~]# kubectl get pods -n ingress-nginx -w  -o wide
NAME                                        READY     STATUS    RESTARTS   AGE       IP            NODE      NOMINATED NODE
default-http-backend -6586 bc 58 b 6 -qd 9 fk        1 / 1        Running    0           11 h        10.244 . 1.95    node 1      < none >
nginx-ingress-controller -6 bd 7 c 597 cb-jlqzp    1 / 1        Running    3           11 h        10.244 . 1.96    node 1      < none >

 

     能够看到ingress-nginx名称空间里面有两个pod都处于running状态

 

安装service-nodeport

 

    上面咱们把ingress-nginx部署到了1号node上。接下来咱们还须要部署一个service-nodeport服务,才能实现把集群外部流量接入到集群中来。 

 

1
[root@master ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml

 

    咱们为了避免让service nodeport自动分配端口,咱们本身指定一下nodeport,修改文件中加两个nodePort参数,最终以下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@master ingress]# cat service-nodeport.yaml 
apiVersion: v 1
kind: Service
metadata:
   name: ingress-nginx
   namespace: ingress-nginx
   labels:
     app.kubernetes.io/name: ingress-nginx
     app.kubernetes.io/part-of: ingress-nginx
spec:
   type: NodePort
   ports:
   - name: http
     port:  80
     targetPort:  80
     protocol: TCP
     nodePort:  30080
   - name: https
     port:  443
     targetPort:  443
     protocol: TCP
     nodePort:  30443
   selector:
     app.kubernetes.io/name: ingress-nginx
     app.kubernetes.io/part-of: ingress-nginx

 

1
2
[root@master ingress]# kubectl apply -f service-nodeport.yaml 
service/ingress-nginx created

 

1
2
3
4
[root@master ingress]# kubectl get svc -n ingress-nginx
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default-http-backend   ClusterIP    10.110 . 74.183    < none >         80 /TCP                        12 h
ingress-nginx          NodePort     10.102 . 78.188    < none >         80: 30080 /TCP, 443: 30443 /TCP    2 m

 

    上面我看到80对应30080,,43对应30443 

 

    咱们直接经过node1节点的ip就能够访问到应用: 

 

1
2
[root@master ingress]# curl  http:// 172.16 . 1.101: 30080
default  backend -  404

 

 

 

定义myapp service

 

1
[root@master manifests]# mkdir /root/manifests/ingress

 

1
[root@master ~]# kubectl explain service.spec.ports

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@master ingress]# cat deploy-demo.yaml 
apiVersion: v 1
kind: Service
#必须设置为无头service
metadata:
  name: myapp
  namespace:  default
spec:
   selector:
     app: myapp
     release: canary
   ports:
   - name: http
     targetPort:  80    #这是容器port
     port:  80   #这是service port
---
apiVersion: apps/v 1
kind: Deployment
metadata:
   name: myapp-deploy
   namespace:  default
spec:
   replicas:  2
   selector: #标签选择器
     matchLabels: #匹配的标签为
       app: myapp
       release: canary
   template:
     metadata:
       labels:
         app: myapp #和上面的myapp要匹配
         release: canary
     spec:
       containers:
       - name: myapp
         image: ikubernetes/myapp:v 1
         ports:
         - name: http
           containerPort:  80

 

1
2
3
[root@master ingress]# kubectl apply -f deploy-demo.yaml 
service/myapp created
deployment.apps/myapp-deploy unchanged

 

1
2
3
4
[root@master ingress]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP    10.96 . 0.1        < none >         443 /TCP     17 d
myapp        ClusterIP    10.108 . 177.62    < none >         80 /TCP      1 m

 

1
2
3
4
[root@master ingress]# kubectl get pods
NAME                            READY     STATUS             RESTARTS   AGE
myapp-deploy -69 b 47 bc 96 d -79 fqh    1 / 1        Running             0           1 d
myapp-deploy -69 b 47 bc 96 d-tc 54 k    1 / 1        Running             0           1 d

 

 

 

把myapp service经过ingress发布出去

 

     下面咱们再定义一个清单文件,把myapp应用经过Ingress(至关于nginx的反向代理功能)发布出去: 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master ingress]# cat ingress-myapp.yaml 
apiVersion: extensions/v 1 beta 1 
kind: Ingress
metadata:
   name: ingress-myapp
   namespace:  default  #要和deployment和要发布的service处于同一个名称空间
   annotations: #这个注解说明咱们要用到的ingress-controller是nginx,而不是traefic,enjoy
     kubernetes.io/ingress.class:  "nginx"
spec:
   rules:
   - host: myapp.zhixin.com #表示访问这个域名,就会转发到后端myapp管理的pod上的服务:
     http:
       paths: 
       - path:
         backend:
           serviceName: myapp
           servicePort:  80

 

1
2
[root@master ingress]# kubectl apply -f ingress-myapp.yaml 
ingress.extensions/ingress-myapp created

 

1
2
3
[root@master ingress]# kubectl get ingress
NAME            HOSTS              ADDRESS   PORTS     AGE
ingress-myapp   myapp.zhixin.com              80         8 m

 

1
[root@master ingress]# kubectl describe ingress

 

1
2
3
4
[root@master ingress]# kubectl get pods -n ingress-nginx 
NAME                                        READY     STATUS    RESTARTS   AGE
default-http-backend -6586 bc 58 b 6 -qd 9 fk        1 / 1        Running    0           12 h
nginx-ingress-controller -6 bd 7 c 597 cb-jlqzp    1 / 1        Running    3           12 h

 

    进入ingress-controller交互式命令行里面,能够清晰的看到nginx是怎么反向代理咱们myapp.zhixin.com的: 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master ingress]# kubectl exec -n ingress-nginx -it nginx-ingress-controller -6 bd 7 c 597 cb-jlqzp -- /bin/sh
$ cat nginx.conf
## start server myapp.zhixin.com
server {
server_name myapp.zhixin.com ;
listen  80 ;
set $proxy_upstream_name  "-" ;
location / {
set $namespace       "default" ;
set $ingress_name    "ingress-myapp" ;
set $service_name    "myapp" ;
set $service_port    "80" ;
........

 

    测试,下面咱们把myapp.zhixin.com域名解析到node1 ip 172.16.1.101上。

 

1
2
[root@master ingress]# curl myapp.zhixin.com: 30080
Hello MyApp | Version: v 1  | <a href= "hostname.html" >Pod Name</a>

 

 

 

把tomcat service经过ingress发布出去(新例子)

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@master ingress]# cat tomcat-demo.yaml 
apiVersion: v 1
kind: Service
#必须设置为无头service
metadata:
  name: tomcat
  namespace:  default
spec:
   selector:
     app: tomcat
     release: canary
   ports:
   - name: http
     targetPort:  8080    #这是容器port
     port:  8080   #这是service port
   - name: ajp
     targetPort:  8009
     port:  8009
---
apiVersion: apps/v 1
kind: Deployment
metadata:
   name: tomcat-deploy
   namespace:  default
spec:
   replicas:  2
   selector: #标签选择器
     matchLabels: #匹配的标签为
       app: tomcat
       release: canary
   template:
     metadata:
       labels:
         app: tomcat #和上面的myapp要匹配
         release: canary
     spec:
       containers:
       - name: tomcat
         image: tomcat: 8.5 . 34 -jre 8 -alpine  #在https://hub.docker.com/r/library/tomcat/tags/上面找
         ports:
         - name: http
           containerPort:  8080
         - name: ajp
           containerPort:  8009

 

1
2
3
[root@master ingress]# kubectl apply -f tomcat-demo.yaml 
service/tomcat created
deployment.apps/tomcat-deploy created

 

1
2
3
4
[root@master ingress]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
kubernetes   ClusterIP    10.96 . 0.1        < none >         443 /TCP              17 d
tomcat       ClusterIP    10.109 . 76.87     < none >         8080 /TCP, 8009 /TCP    1 m

 

1
2
3
4
[root@master ingress]# kubectl get pods
NAME                             READY     STATUS             RESTARTS   AGE
tomcat-deploy -64 c 4 d 54 df 4 -68 sk 8    1 / 1        Running             0           51 s
tomcat-deploy -64 c 4 d 54 df 4 -7 b 58 g    1 / 1        Running             0           51 s

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master ingress]# cat ingress-tomcat.yaml 
apiVersion: extensions/v 1 beta 1 
kind: Ingress
metadata:
   name: ingress-tomcat
   namespace:  default  #要和deployment和要发布的service处于同一个名称空间
   annotations: #这个注解说明咱们要用到的ingress-controller是nginx,而不是traefic,enjoy
     kubernetes.io/ingress.class:  "nginx"
spec:
   rules:
   - host: tomcat.zhixin.com #表示访问这个域名,就会转发到后端myapp管理的pod上的服务:
     http:
       paths: 
       - path:
         backend:
           serviceName: tomcat
           servicePort:  8080

 

1
2
[root@master ingress]# kubectl apply -f ingress-tomcat.yaml 
ingress.extensions/ingress-myapp configured

 

1
2
3
[root@master ingress]# kubectl get ingress
NAME             HOSTS               ADDRESS   PORTS     AGE
ingress-tomcat   tomcat.zhixin.com              80         11 s

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master ingress]# kubectl describe ingress ingress-tomcat
Name:             ingress-tomcat
Namespace:         default
Address:          
Default backend:  default-http-backend: 80  (< none >)
Rules:
   Host               Path  Backends
   ----               ----  --------
   tomcat.zhixin.com  
                         tomcat: 8080  (< none >)
Annotations:
   kubernetes.io/ingress.class:  nginx
Events:
   Type    Reason  Age   From                      Message
   ----    ------  ----  ----                      -------
   Normal  CREATE   1 m    nginx-ingress-controller  Ingress  default /ingress-tomcat

 

    把tomcat.zhixin.com解析到node1上节点物理ip(个人是172.16.1.101)

 

    测试,能够看到tomcat欢迎界面:

 

1
[root@master ingress]# curl tomcat.zhixin.com: 30080

 

 

 

使用https访问(新例子)

 

一、先作个自签的证书(咱们这里不演示CA的例子) 

 

1
[root@master ingress]# openssl genrsa -out tls.key  2048

 

1
[root@master ingress]# openssl req -new -x 509  -key tls.key  -out tls.crt -subj /C=CN/ST=Beijing/O=DevOps/CN=tomcat.zhixin.com

 

二、经过secret把证书注入到pod中。 

 

1
2
[root@master ingress]# kubectl create secret tls tomcat-infress-secret --cert=tls.crt --key=tls.key 
secret/tomcat-infress-secret created

 

1
2
3
4
[root@master ingress]# kubectl get secret
NAME                    TYPE                                  DATA      AGE
default-token -5 r 85 r     kubernetes.io/service-account-token    3          17 d
tomcat-ingress-secret   kubernetes.io/tls                      2          41 s

 

1
2
3
4
5
6
7
8
9
10
[root@master ingress]# kubectl describe secret tomcat-ingress-secret 
Name:         tomcat-ingress-secret
Namespace:     default
Labels:       < none >
Annotations:  < none >
Type:  kubernetes.io/tls
Data
====
tls.crt:   1245  bytes
tls.key:   1679  bytes

 

三、配置ingress为tls方式

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@master ingress]# cat ingress-tomcat-tls.yaml 
apiVersion: extensions/v 1 beta 1 
kind: Ingress
metadata:
   name: ingress-tomcat-tls
   namespace:  default  #要和deployment和要发布的service处于同一个名称空间
   annotations: #这个注解说明咱们要用到的ingress-controller是nginx,而不是traefic,enjoy
     kubernetes.io/ingress.class:  "nginx"
spec:
   tls:
   - hosts:
     - tomcat.zhixin.com
     secretName: tomcat-ingress-secret #kubectl get secret命令查到的名字
   rules:
   - host: tomcat.zhixin.com #表示访问这个域名,就会转发到后端myapp管理的pod上的服务:
     http:
       paths: 
       - path:
         backend:
           serviceName: tomcat
           servicePort:  8080

 

1
2
3
4
[root@master ingress]# kubectl get ingress
NAME                 HOSTS               ADDRESS   PORTS     AGE
ingress-tomcat       tomcat.zhixin.com             80        2h
ingress-tomcat-tls   tomcat.zhixin.com             80, 443   3m

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master ingress]# kubectl describe ingress ingress-tomcat-tls  
Name:             ingress-tomcat-tls
Namespace:         default
Address:          
Default backend:  default-http-backend: 80  (< none >)
TLS:
   tomcat-ingress-secret terminates tomcat.zhixin.com
Rules:
   Host               Path  Backends
   ----               ----  --------
   tomcat.zhixin.com  
                         tomcat: 8080  (< none >)
Annotations:
   kubectl.kubernetes.io/last-applied-configuration:  { "apiVersion" : "extensions/v1beta1" , "kind" : "Ingress" , "metadata" :{ "annotations" :{ "kubernetes.io/ingress.class" : "nginx" }, "name" : "ingress-tomcat-tls" , "namespace" : "default" }, "spec" :{ "rules" :[{ "host" : "tomcat.zhixin.com" , "http" :{ "paths" :[{ "backend" :{ "serviceName" : "tomcat" , "servicePort" : 8080 }, "path" :null}]}}], "tls" :[{ "hosts" :[ "tomcat.zhixin.com" ], "secretName" : "tomcat-ingress-secret" }]}}
   kubernetes.io/ingress.class:  nginx
Events:
   Type    Reason  Age   From                      Message
   ----    ------  ----  ----                      -------
   Normal  CREATE   4 m    nginx-ingress-controller  Ingress  default /ingress-tomcat-tls

 

四、连如ingress-controller查看nginx.conf的配置 

 

1
2
3
4
[root@master ingress]# kubectl get pods -n ingress-nginx
NAME                                        READY     STATUS    RESTARTS   AGE
default-http-backend -6586 bc 58 b 6 -qd 9 fk        1 / 1        Running    0           16 h
nginx-ingress-controller -6 bd 7 c 597 cb-jlqzp    1 / 1        Running    3           16 h

 

1
2
3
4
5
6
7
8
9
10
11
[root@master ingress]# kubectl exec -n ingress-nginx -it nginx-ingress-controller -6 bd 7 c 597 cb-jlqzp -- /bin/sh
$ $ cat nginx.conf
     ## start server tomcat.zhixin.com
     server {
         server_name tomcat.zhixin.com ;
         
         listen  80 ;
         
         set $proxy_upstream_name  "-" ;
         
         listen  443   ssl http 2 ;

 

    看到有listen 443了。 

 

五、测试https 

 

1
[root@master ingress]# curl https://tomcat.zhixin.com: 30443

 

部署方法三(利用ingress 的80端口)

 

    前面两种部署方法,是用node ip + 非80端口,访问k8s集群内部的服务。但是,咱们实际生产中更但愿的是node ip + 80端口的方式,访问k8s集群内的服务。我感受这个方法最好,下面就就介绍这个方法。 

 

    这部份内容参考的是博文http://blog.51cto.com/devingeng/2149377

 

    下载地址 

 

https://github.com/kubernetes/ingress-nginx/archive/nginx-0.11.0.tar.gz

 

1
2
3
4
5
6
7
8
ingress-nginx文件位于deploy目录下,各文件的做用:
configmap.yaml:提供configmap能够在线更行nginx的配置
default-backend.yaml:提供一个缺省的后台错误页面  404
namespace.yaml:建立一个独立的命名空间 ingress-nginx
rbac.yaml:建立对应的role rolebinding 用于rbac
tcp-services-configmap.yaml:修改L 4 负载均衡配置的configmap
udp-services-configmap.yaml:修改L 4 负载均衡配置的configmap
with-rbac.yaml:有应用rbac的nginx-ingress-controller组件

 

    修改with-rbac.yaml

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
apiVersion: extensions/v 1 beta 1
kind: Daemonset
metadata:
   name: nginx-ingress-controller
   namespace: ingress-nginx 
spec:
   selector:
     matchLabels:
       app: ingress-nginx
   template:
     metadata:
       labels:
         app: ingress-nginx
       annotations:
         prometheus.io/port:  '10254'
         prometheus.io/scrape:  'true'
     spec:
       serviceAccountName: nginx-ingress-serviceaccount      
       hostNetwork: true
       containers:
         - name: nginx-ingress-controller
           image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller: 0.11 . 0
           args:
             - /nginx-ingress-controller
             - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
             - --configmap=$(POD_NAMESPACE)/nginx-configuration
             - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
             - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
             - --annotations-prefix=nginx.ingress.kubernetes.io
           env:
             - name: POD_NAME
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.name
             - name: POD_NAMESPACE
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
           ports:
           - name: http
             containerPort:  80
           - name: https
             containerPort:  443
           livenessProbe:
             failureThreshold:  3
             httpGet:
               path: /healthz
               port:  10254
               scheme: HTTP
             initialDelaySeconds:  10
             periodSeconds:  10
             successThreshold:  1
             timeoutSeconds:  1
           readinessProbe:
             failureThreshold:  3
             httpGet:
               path: /healthz
               port:  10254
               scheme: HTTP
             periodSeconds:  10
             successThreshold:  1
             timeoutSeconds:  1
       nodeSelector:
         custom/ingress-controller-ready:  "true"

 

须要修改的地方:

 

kind: DaemonSet:官方原始文件使用的是deployment,replicate 为 1,这样将会在某一台节点上启动对应的nginx-ingress-controller pod。外部流量访问至该节点,由该节点负载分担至内部的service。测试环境考虑防止单点故障,改成DaemonSet而后删掉replicate ,配合亲和性部署在制定节点上启动nginx-ingress-controller pod,确保有多个节点启动nginx-ingress-controller pod,后续将这些节点加入到外部硬件负载均衡组实现高可用性。

 

hostNetwork: true:添加该字段,暴露nginx-ingress-controller pod的服务端口(80)

 

nodeSelector: 增长亲和性部署,有custom/ingress-controller-ready 标签的节点才会部署该DaemonSet

 

为须要部署nginx-ingress-controller的节点设置lable

 

1
2
3
kubectl label nodes vmnode 2  custom/ingress-controller-ready=true
kubectl label nodes vmnode 3  custom/ingress-controller-ready=true
kubectl label nodes vmnode 4  custom/ingress-controller-ready=true

 

加载yaml文件

 

1
2
3
4
5
6
7
kubectl apply  -f namespace.yaml
kubectl apply -f default-backend.yaml
kubectl apply -f configmap.yaml
kubectl apply -f tcp-services-configmap.yaml
kubectl apply -f udp-services-configmap.yaml
kubectl apply -f rbac.yaml
kubectl apply -f with-rbac.yaml

 

查看pod是否正常建立

 

##下载镜像可能会比较慢,等待一会全部pod都是Running状态,按Ctrl + c 退出

 

1
2
3
4
5
6
[root@vmnode 1  deploy]# kubectl get pods --namespace=ingress-nginx  --watch
NAME                                    READY     STATUS    RESTARTS   AGEdefault-
http-backend -6 c 59748 b 9 b-hc 8 q 9    1 / 1        Running    0           6 m
nginx-ingress-controller -7 fmlp           1 / 1        Running    1           13 d
nginx-ingress-controller-j 95 fb           1 / 1        Running    1           13 d
nginx-ingress-controller-ld 2 jw           1 / 1        Running    1           13 d

 

测试ingress 

 

建立一个tomcat的Service

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@k 8 s-master 1  test]# cat mytomcat.yaml 
apiVersion: extensions/v 1 beta 1
kind: Deployment
metadata:
   name: mytomcat
spec:
   replicas:  2
   template:
     metadata:
       labels:
         run: mytomcat
     spec:
       containers:
       - name: mytomcat
         image: tomcat
         ports:
         - containerPort:  8080
---
apiVersion: v 1
kind: Service
metadata:
   name: mytomcat
   labels:
     run: mytomcat
spec:
   type: NodePort
   ports:
   - port:  8080
     targetPort:  8080
   selector:
     run: mytomcat

 

1
[root@k 8 s-master 1  test]# kubectl apply -f mytomcat.yaml

 

    配置ingress转发文件: 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@k 8 s-master 1  test]# cat test-ingress.yaml 
apiVersion: extensions/v 1 beta 1
kind: Ingress
metadata:
   name: test-ingress
   namespace:  default
spec:
   rules:
   - host: test.zhixin.com
     http:
       paths:
       - path: /
         backend:
           serviceName: mytomcat
           servicePort:  8080

 

host: 对应的域名  

 

path: url上下文 

 

backend:后向转发 到对应的 serviceName: servicePort:

 

1
2
[root@k 8 s-master 1  test]# kubectl apply -f test-ingress.yaml 
ingress.extensions/test-ingress created

 

nginx-ingress-controller运行在node1和nod2两个节点上。若是网络中有dns服务器,在dns中把这两个域名映射到nginx-ingress-controller运行的任意一个节点上,若是没有dns服务器只能修改host文件了。 

 

正规的作法是在node1和node2这两个节点上安装keepalive,生成一个vip。在dns上把域名和vip作映射。

 

我这里直接在node1节点上操做了:

 

我这里node1节点的ip是172.16.22.201;node2节点的ip是172.16.22.202

 

1
2
[root@k 8 s-master 1  test]# echo  " 172.16.22.201 test.zhixin.com"  >> /etc/hosts
[root@k 8 s-master 1  test]# echo  "172.16.22.202 test.zhixin.com"  >> /etc/hosts

 

    而后访问测试: 

 

 

 

 

    看到,咱们把域名test.zhixin.com绑定到Node节点的ip补上,而后咱们直接访问http://test.zhixin.com,就能访问到k8s集群里面的pod服务。 

 

 

 

(7)Ingress Controller及部署

(8)Ingress使用案例:发布httphttpstomcat服务

6、K8S-存储卷

(1)存储卷及其功用

(2)常见的存储卷类型及应用:emptyDirhostPathnfsglusterfs

(3)PVPVC

(4)StorageClassPV的动态供给

(5)ConfigMap

(6)Secret

7、StatefulSet

(1)有状态及无状态应用对比

(2)有状态应用的容器难题

(3)StatefulSet及其应用

(4)案例

8、网络模型及网络策略

(1)flannel工做原理及host-gw等实现方式

(2)calico及其应用

(3)网络策略及其工做机制

(4)基于calico的网络策略的实现

9、认证、受权及准入控制

(1)Kubernetes的认证、受权及准入控制机制

(2)ServiceAccount

(3)令牌认证及证书认证

(4)RBAC及其实现机制

(5)RoleRoleBinding

(6)ClusterRoleClusterRoleBinding

10、调度器

(1)资源需求、资源限额及其应用

(2)Pod优选级类别

(3)Pod调度器工做原理

(4)预选及预选策略

(5)优选及优选算法

(6)高级调度方法

11、资源监控及HPA(陆续上传)

(1)HeapSterInfluxDBGrafana实现资源监控

(2)HPA v1

(3)PrometheusGrafana实现资源监控

(4)Metrics-Server

(5)HPA v2

12、helm及日志收集系统(陆续上传)

(1)helm工做原理

(2)helm部署及其应用

(3)部署efk日志收集系统

十3、基于KubernetesDevOps介绍 (陆续上传)