DOCKER 学习笔记9 Kubernetes (K8s) 生产级容器编排 上

前言

在上一节的学习中。我们已经可以通过最基本的 Docker Swarm 创建集群,然后在集群里面加入我们需要运行的任务 以及任务的数量 这样我们就创建了一个服务。 当然,这样的方式在我们本地虚拟机的情况下,完全适用,并且对于

  • 容器
  • 虚拟主机
  • swarm 创建节点组成集群

有一个很好的理解作用。本节将继续学习关于 Kubernetes (K8s) 的内容。

Kubernetes 建立在 Google 15年的生产工作负载管理经验的基础上,结合了来自社区的最佳理念和实践。

Kubernetes (K8s)

Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。
在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。

节点与管理节点

在K8s 集群包括两种类型的资源

  • 普通节点 Node 一般用于服务
  • 管理节点 Master 用于管理其他节点

Master 管理节点

Master 负责管理集群。 主服务器协调集群中的所有活动,例如调度应用程序、维护应用程序的期望状态、缩放应用程序和推出新的更新。

Node 服务节点

Node 是作为 Kubernetes 集群中的工作机器的 VM 或物理计算机。 每个节点都有一个 Kubelet,它是管理节点和与 kubernets 主节点通信的代理。 节点还应该具有处理容器操作的工具,如 Docker

这个还是和在上一节当中学习的Swarm 虚拟机中通过 docker swarm init xx
其实还是有类似的地方的。

image.png

服务执行过程

当您在 Kubernetes 上部署应用程序时,您告诉主控程序启动应用程序容器。 主服务器安排容器在集群节点上运行。 节点使用主服务器公开的 Kubernetes API 与主服务器通信。 最终用户还可以直接使用 Kubernetes API 与集群交互。

windows 安装 kubectl 以及 minikube

若没有安装 Docker-toolbox 的同学请参考并安装:

https://blogs.chaobei.xyz/archives/docker6

下载 kubectl

Kubernetes 命令行工具 kubectl 允许您针对 Kubernetes 集群运行命令。 您可以使用 kubectl 部署应用程序、检查和管理集群资源以及查看日志。

https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/windows/amd64/kubectl.exe

修改名称为 kubectl.exe

复制到和docker-toolbox 一样的目录下,方便执行

image.png

$ kubectl.exe version  
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-07T21:20:10Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"windows/amd64"}

下载 minikube

https://github.com/kubernetes/minikube/releases/

选择合适的版本后,下载,并且修改名称为 minikube.exe 放到与上面一样的位置下。

$ minikube.exe version                                                                                                 minikube version: v1.7.2
commit: 50d543b5fcb0e1c0d7c27b1398a9a9790df09dfb

使用 minikube 创建集群

minikube start --image-repository=registry.aliyuncs.com/google_containers --registry-mirror=https://fime0zji.mirror.aliyuncs.com --iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.7.0.iso
  • --image-repository 指定使用国内的镜像仓库
  • --registry-mirror 将指定的地址传递给虚拟机docker 作为拉取镜像的地址
  • --iso-url 指定minikubo 镜像的地址。

因为国内防火墙的限制,所以需要将发部分指定为国内地址才可以正常进行。


$ minikube start --image-repository=registry.aliyuncs.com/google_containers --registry-mirror=https://fime0zji.mirror.aliyuncs.com
* Microsoft Windows 10 Pro 10.0.18363 Build 18363 上的 minikube v1.7.2
* Automatically selected the virtualbox driver
* 正在使用镜像存储库 registry.aliyuncs.com/google_containers
* 正在创建 virtualbox 虚拟机(CPUs=2,Memory=2000MB, Disk=20000MB)...
* 找到的网络选项:
  - NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
  - no_proxy=192.168.99.100,192.168.99.102,192.168.99.103
* 正在 Docker 19.03.5 中准备 Kubernetes v1.17.2…
  - env NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
  - env NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
* 正在启动 Kubernetes ...
* Enabling addons: default-storageclass, storage-provisioner
* 等待集群上线...
* 完成!kubectl 已经配置至 "minikube"

官网在线测试环境 https://kubernetes.io/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive/

可能遇到的问题

* 正在下载 kubectl v1.17.2
* 正在下载 kubeadm v1.17.2
* 正在下载 kubelet v1.17.2

它可能一直在下载,真的是一直在下,我第一次使用的时候,我足足等了一个小时,现在想起来真的是 MMP 😂

解决方案

  • 找到其所下载的版本
  • 通过FQ的方式下载到本地,放到cache 缓存文件夹下。

kubeadm https://storage.googleapis.com/kubernetes-release/release/v1.17.2/bin/linux/amd64/kubeadm
kubelet https://storage.googleapis.com/kubernetes-release/release/v1.17.2/bin/linux/amd64/kubelet
kubectl.http://mirror.azure.cn/kubernetes/kubectl/v1.17.2/bin/linux/amd64/kubectl

从上面的下载地址里面修改版本号即可下载你想要的版本。

需要FQ上网才能下载,你懂得

image.png

Kubernetes仪表板

minikube dashboard

$ minikube dashboard
* 正在开启 dashboard ...
* Verifying dashboard health ...
* Launching proxy ...
* Verifying proxy health ...
* Opening http://127.0.0.1:63230/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

image.png

集群状态

kubectl cluster-info

因为我们已经安装了与之交互的 kubectl


$ kubectl.exe cluster-info
Kubernetes master is running at https://192.168.99.113:8443
KubeDNS is running at https://192.168.99.113:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

可以了解到 Kubernets 主节点运行地址以及 Kube 的DNS

获取所有的节点信息

$ kubectl.exe get nodes                                      

NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   31m   v1.17.2

创建APP 镜像

image.png

构建一个node 应用

这个应用需要创建在你的minikube 虚拟机内。而不是本地docker

## 创建一个文件夹
mkdir -p nodetest

## 创建自定义镜像文件并加入以下内容
vi Dockerfile

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

构建测试镜像

docker build -t mynginx:test .

尝试运行测试镜像

$ docker run --name mynginx-d -p 8080:80 mynginx:test

测试访问

因为我们的的镜像是跑在虚拟机当中的,获取其网卡地址后,用8080访问

使用kubectl创建部署

Kubernetes Pod 是一组由一个或多个容器组成的组,为了管理和联网的目的而连接在一起。

当我们在 Kubernetes 上创建一个 Deployment 时,Deployment 会创建包含容器的 Pods (而不是直接创建容器)。 每个 Pod 都绑定到节点的预定位置,直到终止(根据重新启动策略)或删除为止。 如果节点出现故障,则在集群中的其他可用节点上调度相同的 Pods。

image.png

一个 Pod 总是在一个 Node 上运行。 Node 是 Kubernetes 的工作机器,根据集群的不同,它可以是虚拟机,也可以是物理机器。 每个节点由主节点管理。 一个 Node 可以有多个POD,Kubernetes 主机自动处理跨集群中的 Node 的POD调度。 主机的自动调度考虑到了每个节点上的可用资源。

创建一个POD

Pod 是一组或多个应用程序容器(如 Docker 或 rkt) ,包括共享存储(卷)、 IP 地址和有关如何运行它们的信息。

kubectl create deployment mynode --image=mynginx:test

使用 kubectl create 命令创建一个管理 Pod 的 Deployment。 Pod 基于所提供的 Docker 图像运行一个容器。

查看部署

$ kubectl.exe get deployment
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
mynode   1/1     1            1           10s

查看POD

kubectl.exe get pods

$ kubectl.exe get pods                                                                                                  NAME                      READY   STATUS    RESTARTS   AGE
mynode-5479db549c-fm4qk   1/1     Running   0          9m33s

集群事件

kubectl get events

kubectl 配置

kubectl config view

$ kubectl.exe config view                                                                                               apiVersion: v1
clusters:
- cluster:
    certificate-authority: C:\Users\17639\.minikube\ca.crt
    server: https://192.168.99.100:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: C:\Users\17639\.minikube\client.crt
    client-key: C:\Users\17639\.minikube\client.key

创建一个服务暴露你的应用

默认情况下,Pod 只能通过它在 Kubernetes 集群中的内部 IP 地址访问。 要使 hello-node Container 可以从 Kubernetes 虚拟网络外部访问,必须将 Pod 公开为 Kubernetes 服务。

Kubernetes 的服务是一个抽象概念,它定义了一组逻辑 Pods 和一个访问它们的策略。 服务允许独立的Pods 之间的松散耦合。 服务是使用 YAML (首选)或 JSON 定义的,就像所有的 Kubernetes 对象一样。

尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service,这些 IP 不会在集群之外公开。 服务允许应用程序接收流量。 通过在 ServiceSpec 中指定类型,可以以不同的方式公开服务:

  • ClusterIP (default) 公开集群中内部 IP 上的服务。 此类型使服务只能从集群内部访问
  • NodePort 使用 NAT 公开集群中每个选定节点的同一端口上的服务
  • LoadBalancer 负载均衡器,创建一个负载均衡器,并且为服务分配固定IP
  • ExternalName

服务以及标签

image.png

一组PODS 组成一个服务。服务是一种抽象,它允许POD 在节点关闭时候死亡,以及复制。而不会影响到服务的运行。服务内部依赖的PODS 之间的发现和关联都是由Kubernets Service 来处理的。

服务使用标签和选择器来匹配一组PODS

标签是附加在对象上的键值对,可以以任何方式使用。

image.png

这个图里面我们可以发现,在管理节点里面部署了两个应用。每个应用分别将标签app=B app=A 的所有POD 整理起来组成服务。

创建服务

  • kubectl get pods 查看当前所有的POD
  • kubectl get service 查看当前所有服务

$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
mynode-5479db549c-lgtfv   1/1     Running   0          56m

$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   16h

kubectl expose deployment mynode --type=NodePort --port=80
将一个deployment 通过服务的方式暴露出去,暴露端口80,也就是我们容器内部的80端口,mynode 是我们已经部署过的一个应用(资源)。

$ kubectl.exe get service mynginx
NAME      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
mynode    NodePort   10.111.8.25   <none>        80:30857/TCP   5s

这里发现其将我们的服务暴露到了30857下。

此服务的类型:ClusterIP、NodePort、LoadBalancer或ExternalName。默认值为“ClusterIP”。

$ kubectl get deployment                                                                                                                                                                                                                     NAME     READY   UP-TO-DATE   AVAILABLE   AGE
mynode   1/1     1            1           64m

image.png

nodePort

 外部机器可访问的端口。
比如一个Web应用需要被其他用户访问,那么需要配置type=NodePort,而且配置nodePort=30001,那么其他机器就可以通过浏览器访问scheme://node:30001访问到该服务,例如http://node:30001。
 例如MySQL数据库可能不需要被外界访问,只需被内部服务访问,那么不必设置NodePort

targetPort

 容器的端口(最根本的端口入口),与制作容器时暴露的端口一致(DockerFile中EXPOSE),例如docker.io官方的nginx暴露的是80端口。
 docker.io官方的nginx容器的DockerFile参考https://github.com/nginxinc/docker-nginx

port

 kubernetes中的服务之间访问的端口,尽管mysql容器暴露了3306端口(参考https://github.com/docker-library/mysql/的DockerFile),但是集群内其他容器需要通过33306端口访问该服务,外部机器不能访问mysql服务,因为他没有配置NodePort类型

参考:https://www.cnblogs.com/devilwind/p/8881201.html

通过标签的方式查询

kubectl describe <type> <name> 可以查询到我们想看的信息,若不填写名称,则默认管理节点。

$ kubectl describe deployment
Name:                   mynode
Namespace:              default
CreationTimestamp:      Sun, 16 Feb 2020 12:52:50 +0800
Labels:                 app=mynode
.....

可以看到我们部署的资源的标签 app=mynode

kubectl get pods -l app=mynode 加入-l 进行标签查询。

删除服务

kubectl delete service <name> 通过名称删除一个服务

删除 POD deployment

先删除POD 而后删除 Deployment

## 查看所有POD
kubectl get pods
## 查看所有部署
kubectl get deployment

kubectl delete pod <name>

kubectl delete deployment  <name>

参考

遇到的坑

未使用国内镜像仓库


E0215 13:06:36.509035   15568 cache.go:62] save image to file "gcr.io/k8s-minikube/storage-provisioner:v1.8.1" -> "C:\\Users\\17639\\.minikube\\cache\\images\\gcr.io\\k8s-minikube\\storage-provisioner_v1.8.1" failed: nil image for gcr.io/k8s-minikube/storage-provisioner:v1.8.1: Get https://gcr.io/v2/: dial tcp [2404:6800:4008:c03::52]:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

posted @ 2020-02-16 14:48  程序猿小码  阅读(971)  评论(0编辑  收藏  举报