Kubernetes 实战 —— 01. Kubernetes 介绍
Kubernetes 实战 —— 02. 开始使用 Kubernetes 和 Docker
Kubernetes 实战 —— 03. pod: 运行于 Kubernetes 中的容器
Kubernetes 实战 —— 04. 副本机制和其他控制器:部署托管的 pod
Kubernetes 实战 —— 05. 服务:让客户端发现 pod 并与之通信(上
Kubernetes 实战 —— 05. 服务:让客户端发现 pod 并与之通信(下
运行容器
运行
可以运行 Docker 客户端可执行文件来执行各种 Docker 命令。例如:可以试着从 Docker Hub 的公共镜像仓库拉取、运行镜像。 Docker Hub 中有许多随时可用的常见镜像,其中就包括 busybox ,可以用来运行简单的命令,例如: echo “Hello world” 。
docker run busybox echo “Hello world”
原理
执行 docker run 命令后: P25
docker run <image>
docker run <image>:<tag>
Docker 支持同一镜像的多个版本,每个版本必须有唯一的 tag 名,当引用镜像没有显式地指定 tag 时, Docker 会默认指定 tag 为 latest 。
创建应用
const http = require('http');
const os = require('os');
console.log("Kubia server starting...");
var handler = function(request, response) {
console.log("Received request from " + request.connection.remoteAddress);
response.writeHead(200);
response.end("You've hit " + os.hostname() + "\n");
};
var www = http.createServer(handler);
www.listen(8080);
这个应用会接收 HTTP 请求并响应应用运行的服务器真实主机名(非宿主机名),当其部署在 Kubernetes 上并进行伸缩时(水平伸缩,复制应用到多个节点),可以发现 HTTP 请求切换到了应用的不同实例上。
创建 Dockerfile
FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]
构建容器镜像
docker build -t kubia .
上述命令会基于当前目录下的 Dockerfile 文件中的指令创建一个名为 kubia 的镜像。
构建过程不是由 Docker 客户端运行的,而是将整个目录的文件上传到 Docker 守护进程并在那里进行的。如果在一台非 Linux 操作系统中使用 Docker ,客户端运行在宿主机操作系统上,而守护进程运行在一个虚拟机内。
提示: 不要在构建目录中包含任何不需要的文件,这样会减慢构建的速度,尤其是 Docker 守护进程运行在一个远端机器的时候。//加入Java开发交流君样:756584822一起吹水聊天
镜像不是一个大的二进制块,而是由许多层组成的,不同镜像可能会共享分层,这样会让存储和传输变得更加高效。
构建镜像时, Dockerfile 中每一条单独的指令都会创建一个新层,最后一层会被标记为指定的镜像名。
docker run --name kubia-container -p 8080:8080 -d kubia
上述命令会基于 kubia 镜像创建一个叫 kubia-container 的新容器。 -d 表示这个容器与命令行分离,意味着在后台运行。
-p 8080:8080 表示本机上的 8080 端口会映射到容器内的 8080 端口,所以可以通过 localhost:8080 访问这个应用。
docker ps 会打印出每一个容器的 ID 和名称、容器运行所使用的镜像、容器中执行代码命令、创建时间、以及当前状态。
-a: 查看所有容器,包括运行中的和已停止的
获取更多的容器信息
docker inspect kubia-container 可以查看包含容器底层信息的长 JSON 。
探索运行容器的内部
在已有的容器内部运行 shell
docker exec -ti kubia-container bash
上述命令会在已有的 kubia-container 容器内部运行 bash 。 bash 进程会和主容器进程拥有相同的命名空间,可以用于查看 Node.js 和应用是如何在容器里运行的。 P31
docker tag kubia idealism/kubia
上述命令不会重命名标签,而是给同一个镜像创建一个额外的标签。 kubia 和 idealism/kubia 指向同一个镜像 ID ,实际上是同一个镜像的两个标签。
推送镜像
docker push idealism/kubia 可以将本地的镜像推送到 idealism 名下的 kubia 。
在不同机器上运行镜像
推送完成之后,就可以通过 docker run --name kubia-container -p 8080:8080 -d kubia 在任何机器上运行同一个镜像了。
用 Minikube 运行一个本地三节点 Kubernetes 集群
Minikube 是一个构建单节点集群的工具,对于测试 Kubernetes 和本地开发应用都非常有用。
minikube start --nodes 4: 启动一个四节点的 Kubernetes 集群,包含一个主节点和三个工作节点。
kuibectl cluster-info: 展示集群信息
minikube ssh: 登录到 Minikube VM 从内部访问,可以查看在节点上运行的进程
kubectl get nodes: 列出集群的节点
kubectl describe node minikube: 查看指定节点的更多信息
使用 kubectl get nodes 查看当前集群的节点信息如下:
NAME STATUS ROLES AGE VERSION
minikube Ready master 56m v1.18.2
minikube-m02 Ready <none> 13m v1.18.2
minikube-m03 Ready <none> 11m v1.18.2
minikube-m04 Ready <none> 10m v1.18.2
可以发现有三个节点的角色是 ,需要手动将它们的 ROLES 设置为 worker ,运行如下命令即可:
kubectl label node minikube-m02 node-role.kubernetes.io/worker=worker
kubectl label node minikube-m03 node-role.kubernetes.io/worker=worker
kubectl label node minikube-m04 node-role.kubernetes.io/worker=worker
部署 Node.js 应用
kubectl create deployment kubia --image=idealism/kubia
上述命令无须配置文件即可创建一个名为 kubia 的 development (可以使用 kubectl get developments 查看),同时自动创建一个名称前缀为 kubia 的 pod (可以使用 kubectl get pods 查看)。
Kubernetes 不直接处理单个容器,它使用多个共存容器的理念,这组容器叫作 pod 。
一个 pod 是一组紧密相关的容器,它们总是一起运行在同一个工作节点上,以及同一个 Linux 命名空间中。
每个 pod 就像一个独立的逻辑机器,拥有自己的 IP 、主机名、进程等,运行一个独立的应用程序。
应用程序可以是单个进程,运行在单个容器中,也可以是一个主应用进程和其他支持进程,每个进程都在自己的容器中运行。
一个 pod 的所有容器都运行在同一个逻辑机器上,而其他 pod 中的容器,即使运行在同一个工作节点上,也是运行在不同的逻辑机器上
幕后发生的事情
上图显示了在 Kubernetes 中运行容器镜像所必须的两个步骤:
构建镜像并将其推送到 Docker Hub
命令向 Kubernetes API 服务器发送一个 REST HTTP 请求
创建一个新的 pod ,调度器将其调度到一个工作节点上
Kubelet 看到 pod 被调度到节点上,就告知 Docker 从镜像中心中拉取指定的镜像,因为本地没有该镜像
下载镜像后, Docker 创建并运行容器
调度 (scheduling): 将 pod 分配给一个节点。 pod 会立即执行,而不是将要执行。
通过 kubectl describe pod 可以看到 pod 自己的 IP ,不过这个地址只能从集群内部访问。通过创建一个 LoadBalancer 类型的服务,可以创建一个外部的负载均衡,通过负载均衡的公共 IP 就可以访问 pod 。
kubectl expose deployment kubia --type=LoadBalancer --name kubia-http --port=8080: 对外暴露之前创建的 Pod
大多数资源都有缩写:
po: pod 的缩写
svc: service 的缩写
rc: replicationcontroller 的缩写 (目前已 不推荐使用该控制器 )
deploy: deployment 的缩写
rs: replicaset 的缩写
由于我们使用的是 minikube ,所以没有集成 LoadBalancer ,运行完上述命令后,使用 kubectl get services 会得到如下结果:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 37m
kubia-http LoadBalancer 10.100.74.254 <pending> 8080:32342/TCP 5m52s
//加入Java开发交流君样:756584822一起吹水聊天
可以发现 LoadBalancer 的 EXTERNAL-IP 一直处于 ,我们可以使用 minikube 自带的 minikube tunnel 命令可以完成暴露,运行完后,可得如下结果:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m
kubia-http LoadBalancer 10.100.74.254 10.100.74.254 8080:32342/TCP 7m56s
//加入Java开发交流君样:756584822一起吹水聊天
列出服务
expose 命令的输出是一个名为 kubia-http 的服务。服务是类似于 pod 和 node 的对象,因此可以通过 kubectl get services 命令查看新创建的服务对象。
使用外部 IP 访问服务
curl 10.100.74.254:8080
输出如下:
# You've hit kubia-5b6b94f7f8-h6dbr
可以发现应用将 pod 名称作为它的主机名。
使用 minikube 为集群添加节点可能会导致新增的节点无法访问(在这里耗时几小时终于搞明白了,还是要多读文档 ),可以按照文档中进行设置;当然也有可能是等待的时间不够,设置等操作还没有结束(按照前面的配置了后,还是无法访问,以为哪里操作有问题,各种操作顺序都试了还是无法访问,最后等待了近 10 min 就自动好了。。。)
Deployment 、 pod 和服务是符合组合在一起的
Kubernetes 的基本构建是 pod 。但是,我们前面并没有真的直接创建出任何 pod 。通过运行 kubectl create deployment 命令,创建了一个 Deployment 控制器,它用于创建 pod 实例。为了使该 pod 能够从集群外部访问,需要让 Kubernetes 将该 Deployment 管理的所有 pod 由一个服务对外暴露。
系统中最重要的组件是 pod ,一个 pod 中可以包含任意数量的容器。 pod 有自己独立的私有 IP 地址和主机名。
Deployment 控制器确保始终存在一个运行中的 pod 实例。通常, Deployment 用于复制 pod (即创建 pod 的多个副本)并让它们保持运行。如果 pod 因为任何原因消失了,那么 Deployment 将创建一个新的 pod 来替换消失的 pod 。
系统的第三个组件是 kubia-http 服务。 pod 的存在是短暂的,一个 pod 可能会在任何时候消失(1. 所在节点发生故障; 2. 有人删除了 pod ; 3. pod 被从一个健康的节点剔除了),此时消失的 pod 将被 Deployment 替换为新的 pod 。新旧 pod 具有不同的 IP 地址。所以需要一个服务来解决不断变化的 pod IP 地址的问题,以及在一个固定的 IP 和端口对上对外暴露多个 pod 。
服务表示一组或多组提供相同服务的 pod 的静态地址。到达服务 IP 和端口的请求将被转发到属于该服务的一个容器的 IP 和端口。
kubectl get deployments
输出如下:
# NAME READY UP-TO-DATE AVAILABLE AGE
# kubia 1/1 1 1 49m
使用 kubectl get 可以查看所有类型的资源,上述命令查看所有的 Deployment ,目前仅有一个名为 kubia 的控制器,总共需要 1 个 pod ,目前已有 1 个 pod 已准备好, 1 个 pod 已是最新版本, 1 个 pod 可用。
增加期望的副本数
kubectl scale deployment kubia --replicas=3
# deployment.apps/kubia scaled
上述命令告诉 Kubernetes 需要确保 pod 始终有三个实例在运行。这是 Kubernetes 最基本的原则之一。不告诉 Kubernetes 应该执行什么操作,而是声明性地改变系统的期望状态,并让 Kubernetes 检查当前的状态是否与期望的状态一致。
打到服务上到请求会打到所有到三个 pod 上
curl 10.100.74.254:8080
由于存在三个 pod ,所以有以下三种输出
# You've hit kubia-5b6b94f7f8-h6dbr
# You've hit kubia-5b6b94f7f8-wwbdh
# You've hit kubia-5b6b94f7f8-zzxks
//加入Java开发交流君样:756584822一起吹水聊天
当 pod 有多个实例时 Kubernetes 服务作为负载均衡挡在多个 pod 前面,请求随机地打到不同的 pod 。
kubectl get pods -o wide
# NAME READY STATUS RESTARTS AGE IP NODE ...
# kubia-5b6b94f7f8-h6dbr 1/1 Running 0 12m 10.244.3.2 minikube-m04 ...
# kubia-5b6b94f7f8-wwbdh 1/1 Running 0 12m 10.244.2.2 minikube-m03 ...
# kubia-5b6b94f7f8-zzxks 1/1 Running 0 55m 10.244.1.2 minikube-m02 ...
//加入Java开发交流君样:756584822一起吹水聊天
-o wide: 显示 pod 的 IP 和所运行的节点,以及其他部分信息。
介绍Kubernetes dashboard
访问 Minikube 的 dashboard
minikube dashboard
以上命令会启动 dashboard ,并输出可访问的网址供浏览器中打开。
实际操作时,发现这个命令会一直卡在Verifying proxy health
… 这一行,随后会返回 503 错误,目前 github 上已有类似的 issue 。我按照讨论中的方法发现,kubernetes-dashboard namespace
下的两个 pod 都成功启动了,并且可以通过kubectl port-forward -n kubernetes-dashboard pod/kubernetes-dashboard-696dbcc666-gbgwl 9090:9090
将端口映射到本地并能成功访问。
最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:756584822