Kubernetes 入门

547 阅读13分钟

引言

Kubernetes(常简称为K8s)是用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统。该系统由Google设计并捐赠给Cloud Native Computing Foundation(今属Linux基金会)来使用。它提供“跨主机集群的自动部署、扩展以及运行应用程序容器的平台”。它支持一系列容器工具, 包括Docker等。Kubernetes是当今主流的容器编排框架,承载着Google 15 年生产环境的运维经验,也凝聚了社区的创意和实践。因为Docker宿主机本身的单机性,导致其扩展的局限性,Kubernetes赋予了Docker水平扩展的能力。充分发挥了容器化应用的便捷性,快速性,简单性,健壮性以及强大的扩展能力。

Kubernetes可以将单个计算单元协调链接在一起形成一个高可用性的计算机集群。Kubernetes的抽象能力可以让你将容器化的应用部署在集群中而无需绑定到制定的机器上,这是部署模式的容器化应用在打包时通过一种特殊的打包方式就已经于特定的宿主机完全解耦。不同以往,在虚拟机的部署模式中,应用需要直接被安装在特定的机器上,配置特定的配置文件,与虚拟机或物理机进行深度耦合。而Kubernetes在传统的虚拟机模式上进行更高一级的抽象(得益于Linux容器技术),使得可以以更高效的方式自动在整个集群中进行分配和调度应用容器。

本篇文章会以我在网上搜集到的各种Kubernetes的精华资料(在最后一章节引用会说明资料链接)为基础。进行我自己的一层“理解和尝试”的封装,帮助初学者做一层更高的抽象,希望可以帮助到像我一样的小白人士,对Kubernetes有初步的了解。

基础知识(Basics)

基础概念(Concept)

Kubernetes集群主要有两个资源类型组成:
1.Master: 负责管理和协调整个集群,例如调度应用,维护应用的状态,扩展应用以及为应用更新最新版本。
2.Nodes:可以是一台虚拟机或者是一台物理机,在Kubernetes中作为工作节点对外提供服务,每个节点都有一个Kubelet,它是用于管理节点Pod和机器上运行的容器,并与KubernetesMaster进行通信的代理。节点上还需要具有用于容器操作的工具,例如Dockerrkt。将Kubernetes用于生产环境,至少需要配备三个节点。
3.Pods:是Kubernetes抽象出来,相对于其底下的应用程序来说,犹如一台“逻辑主机”,一个Pod下可以托管一个或多个容器化应用程序,这些应用共享资源,可以将相对紧耦合的不同应用容器在同一个Pod内进行编排。
4.Services:是Kubernetes的一个抽象,它定义Pod的逻辑集合并为这些Pod启用公开服务并与外部环境交互,负载平衡和服务发现。通过在ServiceSpec中指定type,可以以如下不同的方式公开服务:

  • ClusterIP (default) - 在集群的内部IP上公开服务。这种类型只能从集群内部访问服务。
  • NodePort - 使用NAT在集群中每个选定Node的相同端口上公开服务。使用<NodeIP>:<NodePort>从集群外部访问服务。 是ClusterIP的超集。
  • LoadBalancer - 在当前云中创建一个外部负载平衡器(如果支持),并为该服务分配一个固定的外部IP。是NodePort的超集。
  • ExternalName - 通过返回带有该名称的CNAME记录,使用任意名称(在规范中由externalName指定)公开服务。不使用代理。此类型需要v1.7或更高版本的kube-dns支持。

5.Labels:Service使用LabelsSelectors匹配一组Pod,并且允许对其使用一些逻辑操作(示例中会说明),Labels是附加在对象上的键/值对,可以有多种使用用途:

  • 指定用于开发,测试和生产的对象
  • 嵌入版本标签
  • 对象分类

创建集群(Create Cluster)

Kubernetes部署应用时,需要向Master发出指令去启动应用容器。Master会将容器运行在集群的节点上。节点与Master的通信使用其暴露的Kubernetes API,开发者同样也可以直接使用Kubernetes APIMaster进行交互操作。Kubernetes集群可以被部署在物理机或者虚拟机上,初学者可以使用Minikube来搭建学习环境,Minikube是一种轻量级的Kubernetes实现,可以在本地计算机上搭建一个仅包含一个节点的集群。

部署应用(Deploy an App)

Kubernetes集群启动之后,就可以部署容器化应用程序。首先,需要创建一个Deployment配置,Deployment的作用是可以指挥Kubernetes如何创建和更新应用实例。实例创建完成之后,Deployment会持续监控这些实例,假如运行实例的节点被关闭或者删除,则 Deployment 控制器会将该实例替换为集群中另一个节点上的实例。 这提供了一种自我修复机制来解决机器故障维护问题。

部署应用版本迭代(Update an App)

Kubernetes将应用程序扩展为运行多个实例。执行更新的时候,应用程序可以照常对外提供服务。并且在更新期间仅对可用pod进行负载均衡,默认情况下,更新期间不可用的 pod 的最大值和可以创建的新 pod 数都是 1。这两个选项都可以配置为(pod)数字或百分比。并且更新是经过版本控制的,任何 Deployment的更新都可以恢复到以前的(稳定)版本。将应用程序从一个环境提升到另一个环境(原理是通过容器镜像更新)。

完整示例(Examples)

1.minikube环境安装(不推荐,后期使用其拉取镜像创建deployments,pods创建容器时镜像一直拉取失败,原因大家都懂,需要在创建minikube前,设置好代理IP,设置教程
minikube 完整安装教程,安装完成后,输入版本命令,验证是否都安装成功了,命令如下:

minikube version
kubectl version

替换方案使用Docker for Desktop,在Preferences开启Kubernetes即可(如下图,本机为macOS Catalina 10.15.3)。

# 输入以下命令验证
kubectl version
# 含有Service Version表示成功
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"06ad960bfd03b39c8310aaf92d1e7c12ce618213", GitTreeState:"clean", BuildDate:"2020-02-13T18:08:14Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}

2.Kubernetes集群环境创建
输入启动命令进行启动minikube,虚拟管理程序使用VirtualBox

minikube start
# 国内的小伙伴可以使用以下命令
minikube start --vm-driver=virtualbox --registry-mirror=https://registry.docker-cn.com --image-mirror-country=cn --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers

启动完成后,在本地机器上已经有一个正在运行的Kubernetes cluster了。
查看Kubernetes集群的信息命令:

kubectl cluster-info

查看Kubernetes集群下的Nodes数量:

kubectl get nodes

3.Kubernetes部署应用
使用Kubectl create deployment命令进行应用的部署,需要提供部署名称和应用程序镜像位置(包括Docker Hub外部托管映像的完整repository url)。
创建一个Deployment

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

删除一个Deployment

kubectl delete deployments/kubernetes-bootcamp

查看Kubernetes集群下的Deployment数量:

# 安装minikube的本地机器只会有一个
kubectl get deployments

Pods是运行在Kubernetes私有的,独立的网络上,默认情况只会对于在同一Kubernetes集群中的其他PodService中可见,对于该网络外部不可见。如果需要和集群内部的应用进行通信。可以通过kubectl命令行进行交互,也可以使用kubectl命令开出一个代理,就可以直接使用外部网络进行通信。

# 开启代理
kubectl proxy
Starting to serve on 127.0.0.1:8001 #默认占用8001端口
# 使用curl进行外部通信
curl http://localhost:8001/version

4.Kubernetes查看NodesPods工作流程
查看Nodes底下的Pods数量

kubectl get pods

查看Pods创建过程的详细信息

kubectl describe pods #查看所有Pods的信息
kubectl describe pods/<pod name> # 查看单个Pod的信息

# 信息格式如下
Name:         kubernetes-bootcamp-765bf4c7b4-wvrbw
Namespace:    default
Priority:     0
Node:         minikube/172.17.0.23
Start Time:   Tue, 25 Feb 2020 13:42:09 +0000
Labels:       pod-template-hash=765bf4c7b4
              run=kubernetes-bootcamp
Annotations:  <none>
Status:       Running
IP:           172.18.0.6
IPs:
  IP:           172.18.0.6
Controlled By:  ReplicaSet/kubernetes-bootcamp-765bf4c7b4
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://104c3284d26779f27d478565eb4a9392304fd3e838e839c5a272b4aa006b5fee
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Tue, 25 Feb 2020 13:42:15 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8q5zh (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-8q5zh:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8q5zh
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  42s (x4 over 50s)  default-scheduler  0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
  Normal   Scheduled         37s                default-scheduler  Successfully assigned default/kubernetes-bootcamp-765bf4c7b4-wvrbw to minikube
  Normal   Pulled            31s                kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created           30s                kubelet, minikube  Created container kubernetes-bootcamp
  Normal   Started           30s                kubelet, minikube  Started container kubernetes-bootcamp

开启代理,外部计算资源与内部容器交互:

# 开启代理
kubectl proxy

# 设置Pod名称为本机环境变量
export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME

# 指向Pod API的路由。
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
# 返回结果
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-765bf4c7b4-wvrbw | v=1

# 查看日志信息
kubectl logs $POD_NAME

Running On: kubernetes-bootcamp-765bf4c7b4-wvrbw | Total Requests: 1 | App Uptime: 110.181 seconds | Log Time: 2020-02-25T13:44:06.733Z
Running On: kubernetes-bootcamp-765bf4c7b4-wvrbw | Total Requests: 2 | App Uptime: 171.282 seconds | Log Time: 2020-02-25T13:45:07.834Z
Running On: kubernetes-bootcamp-765bf4c7b4-wvrbw | Total Requests: 3 | App Uptime: 252.356 seconds | Log Time: 2020-02-25T13:46:28.908Z
Running On: kubernetes-bootcamp-765bf4c7b4-wvrbw | Total Requests: 4 | App Uptime: 440.729 seconds | Log Time: 2020-02-25T13:49:37.281Z

# 以下部分跟Docker 命令行有些相似
# 查看容器内部环境变量
kubectl exec $POD_NAME env

# 链接进入容器内部
kubectl exec -ti $POD_NAME bash

# 退出容器
exit

root@kubernetes-bootcamp-765bf4c7b4-wvrbw:/# exit

6.使用ServicesLabels,并公开暴露服务

#1.使用NodePort类型创建Service映射端口并公开服务
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

#2.可查看到列表增加了一项新的服务。(本文中为kubernetes-bootcamp)
kubectl get services

#列表
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          19h
kubernetes-bootcamp   NodePort    10.100.220.27   <none>        8080:31283/TCP   23s

#3.使用NodeIP加上NodePort(本文为31283),即可访问到容器内部的服务
curl 172.17.0.76:31283
#返回结果
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5b48cfdcbd-gwh9b | v=1

#4.Deployment会自动会创建一个Label给Pod(文中为app=kubernetes-bootcamp)
kubectl describe deployment
#部分结果
JackPandeMacBook-Pro:~ jackpan$ kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Tue, 25 Feb 2020 22:32:15 +0800
Labels:                 app=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0

#5.通过Label进行Services或者Pods的分类
kubectl get pods -l run=kubernetes-bootcamp #pod分类
kubectl get services -l run=kubernetes-bootcamp # service分类

#6.增加已有pod的Label,Label可以有多个。
kubectl label pod kubernetes-bootcamp-75bccb7d87-dmh89 app=v1 # key值不能重复

#7.使用Label过滤,删除相应的Service
kubectl delete service -l app=v1

7.伸缩应用

# 扩展应用,使用kubectl scale deployments/<deployment-name> --replicas=需要扩展到的副本数
kubectl scale deployments/kubernetes-bootcamp --replicas=4

# 查看结果
kubectl get pods -o wide 

# 结果pods扩展至4条
NAME                                   READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-765bf4c7b4-87ncz   1/1     Running   0          2m36s   172.18.0.7   minikube   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-nxpvv   1/1     Running   0          2m36s   172.18.0.9   minikube   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-xh5r9   1/1     Running   0          26m     172.18.0.6   minikube   <none>           <none>
kubernetes-bootcamp-765bf4c7b4-zqsb5   1/1     Running   0          2m36s   172.18.0.8   minikube   <none>           <none>

# 查看serciec的状态 Endpoints会增加至四个,这样子请求service公开的端口,会将流量负载到这四个pods上。
kubectl describe services/kubernetes-bootcamp

# 缩减应用
kubectl scale deployments/kubernetes-bootcamp --replicas=2

8.应用版本更新

# 更新deployments内的应用的镜像版本到v2
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

# 过几分钟后后,可以发现所有的pod镜像都更新为v2
kubectl describe pods

# rollout status同样可以确认更新状态
kubectl rollout status deployments/kubernetes-bootcamp
# 结果
deployment "kubernetes-bootcamp" successfully rolled out

# 更新至一个错误的版本
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10

# 查看pods信息,可以看到两个pod更新出错了,一个pod被中断。
# 本次更新也不再继续了。剩下三个pod正常运行,系统公开服务在更新出错的情况下还是可以正常运行。
kubectl get pods

# 结果
kubernetes-bootcamp-547469f5dd-lw2v4   0/1     ErrImagePull   0          14s
kubernetes-bootcamp-547469f5dd-vqrb9   0/1     ErrImagePull   0          14s
kubernetes-bootcamp-cfc74666-d5fwf     1/1     Terminating    0          32m
kubernetes-bootcamp-cfc74666-nwccp     1/1     Running        0          36m
kubernetes-bootcamp-cfc74666-rlztx     1/1     Running        0          36m
kubernetes-bootcamp-cfc74666-rs459     1/1     Running        0          36m

# 更新出现异常时,可以回滚至稳定版本。查看pods信息,四个pod都恢复至v2版本
kubectl rollout undo deployments/kubernetes-bootcamp

配置 (Configuration)

Kubernetes使用ConfigMap将配置文件与镜像文件分离,以使容器化的应用程序具有可移植性。以下Kubernetes创建ConfigMapkubectl create configmap命令行的主要三种方式:
创建格式:

kubectl create configmap <map-name> <data-source>

1.通过文件目录创建ConfigMap

# 创建一个本地文件目录
mkdir -p configure-pod-container/configmap/

# 将示例文件下载,放入刚才创建的目录中国呢
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties

# 创建configmap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/

# 查看ConfigMap的详细信息
kubectl describe configmaps game-config

# 输出如下
Name:         game-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

# 以yaml格式输出ConfigMap
kubectl get configmaps game-config -o yaml

# 输出结果
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T18:52:05Z
  name: game-config
  namespace: default
  resourceVersion: "516"
  uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice

2.根据文件创建ConfigMap

# 根据文件创建
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties

# 获取configmap的具体详情在1中已经阐述了,这里不再演示

# 也可根据多个文件创建
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties

3.根据具体的键值对创建ConfigMap

# 指定了两个键值对
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

无状态应用 (Stateless Applications)

状态应用 (Stateful Applications)

集群(Clusters)

服务(Services)

引用(Quote)

如果以下被引用资料造成侵权,请资料所有者联系我删除。
minikube 完整安装教程
kubernetes 官网
Solution of Question:VM is unable to access