Kubernetes入门之本地集群minikube
随着科技的发展,互联网技术更新迭代也越来越快。我们也进入了大数据、微服务、智能AI、物联网、区块链、云的时代。Docker和DevOps的快速发展,企业的架构也发生了重大变化。Kubernetes的出现也让大家的服务更加自动化更加高可用。这篇文章将介绍Kubernetes和基本的使用方法。
什么是Kubernetes
Kubernetes是一个可移植,可扩展的开源平台,用于管理容器化工作负载和服务,有助于声明性配置和自动化。它拥有庞大,快速发展的生态系统。 Kubernetes服务,支持和工具广泛可用。它有自己的学习曲线,因为它引入了各种概念,如Node,Pod,Replication Controller,Health Checks,Services,Labels等。在未来的文章中,我们将分解这些构建块,以了解在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为例子,Windows和Linux基本都是大同小异。各个平台的安装有很多种,选择自己平台最快捷的那个即可。具体可以查看各个平台的安装文档,以下Mac OS的安装方式。
CURL安装
-
下载
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl -
更改权限
chmod +x ./kubectl -
添加到PATH
sudo mv ./kubectl /usr/local/bin/kubectl -
测试
kubectl version
Homebrew安装
-
安装
brew install kubernetes-cli -
测试
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之前,你需要安装HyperKit,VirtualBox, 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。

部署
完成安装之后,我们就可以发布,更新,回滚自己的程序。这个时候我们就需要了解Pod、ReplicaSet、Deployment、Service相关的概念。
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就会自动完成ReplicaSet和pod。下面就创建一个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 rs和kubectl 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

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

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