Kubernetes入门之本地集群minikube

meShell · 2019-07-23

随着科技的发展,互联网技术更新迭代也越来越快。我们也进入了大数据、微服务、智能AI、物联网、区块链、云的时代。DockerDevOps的快速发展,企业的架构也发生了重大变化。Kubernetes的出现也让大家的服务更加自动化更加高可用。这篇文章将介绍Kubernetes和基本的使用方法。

什么是Kubernetes

Kubernetes是一个可移植,可扩展的开源平台,用于管理容器化工作负载和服务,有助于声明性配置和自动化。它拥有庞大,快速发展的生态系统。 Kubernetes服务,支持和工具广泛可用。它有自己的学习曲线,因为它引入了各种概念,如NodePodReplication ControllerHealth ChecksServicesLabels等。在未来的文章中,我们将分解这些构建块,以了解在Kubernetes中如何协调。

Kubernetes 根据Google一个内部项目演变出来的,并且已经运行了十多年的工作量

为什么需要Kubernetes

容器是捆绑和运行应用程序的好方法。在生产环境中,您需要管理运行应用程序的容器并确保没有停机时间。例如,如果容器发生故障,则需要启动另一个容器。如果系统处理这种行为会不会更容易?

这就是为什么需要Kubernetes!Kubernetes为您提供了一个弹性运行分布式系统的框架。它负责您的扩展要求,故障转移,部署模式等。例如,Kubernetes可以轻松管理系统的部署。

它提供终多功能:

  • 服务发现和负载平衡

    Kubernetes可以使用DNS名称或使用自己的IP地址公开容器。如果容器的流量很高,Kubernetes能够负载均衡并分配网络流量,以便部署稳定。

  • 存储编排

    Kubernetes允许您自动安装您选择的存储系统,例如本地存储,公共云提供商等。

  • 自动部署和回滚

    您可以使用Kubernetes描述已部署容器的所需状态,并且可以以受控速率将实际状态更改为所需状态。例如,您可以自动化Kubernetes为您的部署创建新容器,删除现有容器并将所有资源用于新容器。

  • 自动装箱

    Kubernetes允许您指定每个容器需要多少CPU和内存(RAM)。当容器指定了资源请求时,Kubernetes可以更好地决定管理容器的资源。

  • 自动恢复

    Kubernetes重新启动失败的容器,替换容器,杀死不响应用户定义的运行状况检查的容器,并且在它们准备好服务之前不会将它们通告给客户端。

  • 秘钥和配置管理

    Kubernetes允许您存储和管理敏感信息,例如密码,OAuth令牌和ssh密钥。您可以部署和更新机密和应用程序配置,而无需重建容器映像,也不会在堆栈配置中暴露机密。

Kubernetes不是一个传统的,包罗万象的PaaS(平台即服务)系统。由于Kubernetes在容器级而非硬件级运行,因此它提供了PaaS产品常用的一些通用功能,例如部署,扩展,负载平衡,日志记录和监控。但是,Kubernetes不是单片,而且这些默认解决方案是可选的和可插拔的。 Kubernetes提供了构建开发人员平台的构建块,但在重要的地方保留了用户选择和灵活性

安装

上面介绍了基础的概念,现在讲解下怎么安装,以Mac OS为例子,WindowsLinux基本都是大同小异。各个平台的安装有很多种,选择自己平台最快捷的那个即可。具体可以查看各个平台的安装文档,以下Mac OS的安装方式。

CURL安装

  1. 下载

    curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
  2. 更改权限

    chmod +x ./kubectl
  3. 添加到PATH

    sudo mv ./kubectl /usr/local/bin/kubectl
  4. 测试

    kubectl version

Homebrew安装

  1. 安装

    brew install kubernetes-cli
  2. 测试

    kubectl version

zsh命令行中自动完成,将source <(kubectl completion zsh)加入到.zshrc文件中,重启终端。

验证配置

为了让kubectl能够查找和访问Kubernetes集群,它需要一个kubeconfig文件,该文件是在使用kube-up.sh创建集群或成功部署Minikube集群时自动创建的。默认情况下,kubectl配置位于 〜/.kube/config

通过获取群集状态检查kubectl是否已正确配置:


meshell@docker# kubectl cluster-info

在没有安装Minikube之前命令会报下面的错误

Kubernetes master is running at http://localhost:8080

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
The connection to the server localhost:8080 was refused - did you specify the right host or port?

安装Minikube

Kubernetes本地集群需要单独安装Minikube工具。我们可以能过Homebrew来进行安装.

brew cask install minikube

安装完成之后。执行启动命令来创建一个本地的集群服务.

minikube start

如果出现machine does not exist错误,你需要执行minikube delete命令

在启动minikube start之前,你需要安装HyperKitVirtualBox, VMware Fusion其中一个. 当然你也可以使用无VM模式minikube start --vm-driver=none

此命令第一次需要等待很久。

启动成功会看到下面一样的输出,之后我们就可以愉快的玩耍Kubernetes了.

��  minikube v1.2.0 on darwin (amd64)
��  Tip: Use 'minikube start -p <name>' to create a new cluster, or 'minikube delete' to delete this one.
��  Re-using the currently running virtualbox VM for "minikube" ...
⌛  Waiting for SSH access ...
��  Configuring environment for Kubernetes v1.15.0 on Docker 18.09.6

��  Downloading kubelet v1.15.0
��  Relaunching Kubernetes v1.15.0 using kubeadm ...
⌛  Verifying: apiserver proxy etcd scheduler controller dns
��  Done! kubectl is now configured to use "minikube"

如果需要使用本地的Docker服务,需要执行eval $(minikube docker-env)命令. 这样本地的docker可以和minikube虚拟机中的docker可以通信.

Dashboard

Dashboard是基于Web的Kubernetes用户界面。 您可以使用Dashboard将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,以及管理集群资源。 您可以使用Dashboard来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如部署,作业,守护进程等)。 例如,您可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序。 仪表板还提供有关群集中Kubernetes资源状态以及可能发生的任何错误的信息。

启动好minikube start之后,就可以执行minikube dashboard自动打开浏览器再打开Dashboard

k8s-dashboard

部署

完成安装之后,我们就可以发布,更新,回滚自己的程序。这个时候我们就需要了解PodReplicaSetDeploymentService相关的概念。

Pod

Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。

一个Pod封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络IP以及管理控制容器运行方式的策略选项。Pod代表部署的一个单位:Kubernetes中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

Docker是Kubernetes Pod中最常见的runtime ,Pods也支持其他容器runtimes。

Kubernetes中的Pod使用可分两种主要方式:

  • Pod中运行一个容器。“one-container-per-Pod”模式是Kubernetes最常见的用法; 在这种情况下,你可以将Pod视为单个封装的容器,但是Kubernetes是直接管理Pod而不是容器。
  • Pods中运行多个需要一起工作的容器。Pod可以封装紧密耦合的应用,它们需要由多个容器组成,它们之间能够共享资源,这些容器可以形成一个单一的内部service单位 - 一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理

每个Pod都是运行应用的单个实例,如果需要水平扩展应用(例如,运行多个实例),则应该使用多个Pods,每个实例一个Pod。在Kubernetes中,这样通常称为Replication。Replication的Pod通常由Controller创建和管理。

ReplicaSet

ReplicaSet的目的是在任何给定时间维护一组稳定的副本Pod。因此,它通常用于保证指定数量的相同Pod的可用性。

如何使用ReplicaSet

大多数kubectl 支持Replication Controller 命令的也支持ReplicaSets。rolling-update命令除外,如果要使用rolling-update,请使用Deployments来实现。

虽然ReplicaSets可以独立使用,但它主要被Deployments用作pod机制的创建、删除和更新。当使用Deployment时,你不必担心创建pod的ReplicaSets,因为可以通过Deployment实现管理ReplicaSets。

何时使用ReplicaSet

ReplicaSet能确保运行指定数量的pod。然而,Deployment是一个更高层次的概念,它能管理ReplicaSets,并提供对pod的更新等功能。因此,我们建议你使用Deployment来管理ReplicaSets,除非你需要自定义更新编排。

这意味着你可能永远不需要操作ReplicaSet对象,而是使用Deployment替代管理 。

Deployment

Deployment为Pod和ReplicaSet(升级版的Replication Controller)提供声明式更新。

你只需要在Deployment中描述您想要的目标状态是什么,Deployment controller就会帮您将Pod和ReplicaSet的实际状态改变到您的目标状态。您可以定义一个全新的Deployment来创建ReplicaSet或者删除已有的Deployment并创建一个新的来替换。

Note: 您不该手动管理由Deployment创建的ReplicaSet,否则您就篡越了Deployment controller的职责!

典型的用例如下:

  • 使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。
  • 然后,通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
  • 如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
  • 扩容Deployment以满足更高的负载。
  • 暂停Deployment来应用PodTemplateSpec的多个修复,然后恢复上线。
  • 根据Deployment的状态判断上线是否hang住了。
  • 清除旧的不必要的ReplicaSet

创建第一个Deployment

从上面的描述得知,我们只需要创建好Deployment就会自动完成ReplicaSetpod。下面就创建一个Nginx的Deployment。

在Kubernetes中创建对象时,必须提供描述其所需Status的对象Spec,以及关于对象(如name)的一些基本信息。当使用Kubernetes API创建对象(直接或通过kubectl)时,该API请求必须将该信息作为JSON包含在请求body中。通常,可以将信息提供给kubectl .yaml文件,在进行API请求时,kubectl将信息转换为JSON。

一个描述运行nginx:1.16.0 Docker镜像的部署:


apiVersion: extensions/v1beta1 # for versions before 1.16.0 use extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment # deployment的名称
spec:
  selector:
    matchLabels:
      app: nginx # 选择器必须匹配 template中的metadata.labels
  replicas: 3 # tells deployment to run 3 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.0
        ports:
        - containerPort: 80

执行下面命令:


meShell@k8s$ kubectl create -f ./nginx-deployment.yaml --record
deployment "nginx-deployment" created

将kubectl的–record的flag设置为true可以在annotation中记录当前命令创建或者升级了该资源。这在未来会很有用,例如,查看在每个 Deployment revision中执行了哪些命令。

查看创建之后的效果:


meShell@k8s$ kubectl get deployments

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           5m23s
  • NAME 列出群集中的部署名称。
  • DESIRED 显示应用程序的所需副本数,您在创建部署时定义这些副本。这是理想的状态。
  • CURRENT 显示当前正在运行的副本数量。
  • UP-TO-DATE 显示已更新以实现所需状态的副本数。
  • AVAILABLE 显示用户可以使用的应用程序副本数。
  • AGE 显示应用程序运行的时间。

所有的replica都已经是最新的了(包含最新的pod template),可用的(根据Deployment中的.spec.minReadySeconds声明,处于已就绪状态的pod的最少个数)。执行kubectl get rskubectl get pods会显示Replica Set(RS)和Pod已创建。


meShell@k8s$ kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-7d9d7464fb   3         3         3       9m44s


meShell@k8s$ kubectl get pod                                   
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7d9d7464fb-mrc4h   1/1     Running   0          11m
nginx-deployment-7d9d7464fb-rn55g   1/1     Running   0          11m
nginx-deployment-7d9d7464fb-sdd5h   1/1     Running   0          11m

Service

一种抽象的方式暴露在一组运行的应用程序Pods作为网络服务。

使用Kubernetes,您无需修改​​应用程序即可使用不熟悉的服务发现机制。Kubernetes为Pods提供了自己的IP地址和一组Pod的单个DNS名称,并且可以在它们之间进行负载均衡。

定义服务

Kubernetes中的服务是一个REST对象,类似于Pod。与所有REST对象一样,您可以POST向API服务器定义服务以创建新实例。

我们为刚才的nginx-deployment创建服务对象:

kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort # 为POD开放端口
  ports:
  - protocol: TCP
    port: 80
    nodePort: 30000 # 30000流量转到80端口

执行kubectl apply -f nginx-service.yaml来创建Service


meShell@k8s$ kubectl apply -f nginx-service.yaml
service/nginx-service created

在静态端口(NodePort)上的每个节点的IP上公开服务。ClusterIP服务,向其中的NodePort服务的路由,自动创建。您可以NodePort通过请求从群集外部联系服务

如果你使用的是minikube, 你通过minikube service nginx-service --url来获取访问入口


meShell@k8s$ minikube service nginx-service --url

http://192.168.99.105:30000

nginx-service

NodePort一般是配全externalIPs一起使用。如果你是本地使用,你可以使用端口转发。下面的命令就建立了一个端口转发:

meShell@k8s$ kubectl port-forward nginx-deployment-7d9d7464fb-mrc4h 30001:80
Forwarding from 127.0.0.1:30001 -> 80
Forwarding from [::1]:30001 -> 80

在浏览器打开http://127.0.0.1:30001/和上面是同样的效果。

kubectl port-forward需要的是pod名称, 你可以通过kubectl get pods得到名称.

Ingress

上面我们是能过暴露外部的端口来进行访问服务。现在我们将使用Ingress来访问Pods。Ingress将集群外部的HTTP和HTTPS路由暴露给集群中的 服务。流量路由由Ingress资源上定义的规则控制。


    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

可以将Ingress配置为为服务提供外部可访问的URL,负载平衡流量,终止SSL/TLS以及提供基于名称的虚拟主机。一个入口控制器负责履行入口,通常有一个负载均衡器,虽然它也可以配置您的边缘路由器或额外的前端,以帮助处理流量。

Ingress不会暴露任意端口或协议。将除HTTP和HTTPS之外的服务暴露给互联网通常使用Service.Type = NodePort或 Service.Type = LoadBalancer类型的服务。

为了使Ingress资源正常工作,群集必须运行入口控制器(Ingress Controller)。

与作为kube-controller-manager二进制文件一部分运行的其他类型的控制器不同,Ingress控制器不会自动与集群一起启动。使用此页面选择最适合您的群集的入口控制器实施。

Kubernetes作为一个项目目前支持和维护GCE和nginx控制器。

minikube开启Ingress Controller只需要执行下面的命令:

meShell@k8s$ minikube addons enable ingress
✅  ingress was successfully enabled

创建Ingress

定义下面的配置文件ingress-nginx.yaml。执行“

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: \"false\"
spec:
  rules:
    - host: loocode.de # 定义hostname
      http:            # 访问协议
        paths:         # 路径
        - path: /      # 可以指定多个路径为不同的服务
          backend:
            serviceName: nginx-service
            servicePort: 80

输入下面命令来创建对象:

meShell@k8s$ kubectl apply -f ingress-nginx.yaml

查看创建之后的服务

meShell@k8s$ kubectl get ingress
NAME            HOSTS        ADDRESS     PORTS   AGE
nginx-ingress   loocode.de   10.0.2.15   80      14h

使用minikube ip查集群IP。通过修改/etc/hosts将设定的host指定到集群IP

meShell@k8s$  minikube ip
192.168.99.105

修改/etc/hosts文件。

windows目录 C:\window\system32\drivers\etc\hosts

192.168.99.105 loocode.de

ingress-nginx-service

通过上面的介绍讲解,对kubernetes有个基础的概念,对其的使用也是很基础。我们将在下期的文章主要讲解每一个对象和一些微服务的示例。

推荐阅读

  1. https://kubernetes.io/docs/tasks/
  2. https://kubernetes.io/blog/
  3. https://www.mirantis.com/blog/introduction-to-yaml-creating-a-kubernetes-deployment/
  4. https://kubernetes.io/docs/tasks/tools/install-minikube/