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介紹 (陸續上傳)

相關文章
相關標籤/搜索