热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何进行minikube部署本地镜像实践与k8s网络架构分析

如何进行minikube部署本地镜像实践与k8s网络架构分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文

如何进行minikube部署本地镜像实践与k8s网络架构分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

在 windows10 的 WSL2 里用minikube搭建了一个k8s环境,但是每次拉取镜像都很慢甚至失败(原因大家都懂的), 本文的方案的原理是, 先将镜像在宿主机上f-q拉取到本地, 再由minikube 虚机中的k8s 来拉取本地镜像, 这样即可解决之前的拉取镜像失败,也可提升拉取镜像的速度;

两种方案
把私有镜像仓库docker registry 搭建在宿主机上, k8s从本地宿主机上拉取镜像;
把本地镜像推送到minikube的私有镜像仓库上, k8s从minikube的私有镜像仓库(k8s的本地私有镜像仓库)拉取镜像;

1、构建一个镜像

一个完整镜像通常包含应用本身和操作系统,当然还包含需要的依赖软件。

首先准备一个应用。新建一个本文文件,起名叫 app.py,写入下面的内容,实现一个简单的web应用:

from flask import Flask
import socket
import os

app = Flask(__name__)


@app.route('/')
def hello():
    html = "

Hello {name}!

" \            "主机名: {hostname}
"     return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname()) if __name__ == "__main__":     app.run(host='0.0.0.0', port=8082)

在这段代码中,使用 Flask 框架启动了一个 Web 服务器,而它唯一的功能是:如果当前环境中有“NAME”这个环境变量,就把它打印在“Hello”后,否则就打印“Hello world”,最后再打印出当前环境的 hostname。
这个应用的依赖文件requirements.txt存在于与app.py同级目录中,内容是:

$ cat requirements.txt
Flask

将这样一个应用在容器中跑起来,需要制作一个容器镜像。Docker使用Dockerfile文件来描述镜像的构建过程。在本文中,Dockerfile内容定义如下:

# FROM指令指定了基础镜像是python:3.6-alpine,这个基础镜像包含了Alpine Linux操作系统和python3.6
FROM python:3.6-alpine
# WORKDIR指令将工作目录切换为 /app
WORKDIR /app
# ADD指令将当前目录下的所有内容(app.py、requirements.txt)复制到镜像的 /app 目录下
ADD . /app
# RUN指令运行 pip 命令安装依赖
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
# EXPOSE指令暴露允许被外界访问的8082端口
EXPOSE 8082
# ENV指令设置环境变量NAME
ENV NAME World
# CMD指令设置容器内进程为:python app.py,即:这个 Python 应用的启动命令
CMD ["python", "app.py"]

这个Dockerfile中用到了很多指令,把包括FROM、WORKDIR、ADD、RUN、EXPOSE、ENV和CMD。指令的具体含义已经以注释的方式写在了Dockerfile中,大家可以查看。通常我们构建镜像时都会依赖一个基础镜像,基础镜像中包含了一些基础信息,我们依赖基础构建出来的新镜像将包含基础镜像中的内容。

需要再详细介绍一下CMD指令。CMD指定了python app.py为这个容器启动后执行的进程。CMD [“python”, “app.py”] 等价于在容器中执行 “python app.py”。

另外,在使用 Dockerfile 时,还有一种 ENTRYPOINT 指令。它和 CMD 都是 Docker 容器进程启动所必需的参数,完整执行格式是:“ENTRYPOINT CMD”。

默认情况下,Docker 会为你提供一个隐含的 ENTRYPOINT,即:/bin/sh -c。所以,在不指定 ENTRYPOINT 时,比如在我们这个例子里,实际上运行在容器里的完整进程是:/bin/sh -c “python app.py”,即 CMD 的内容就是 ENTRYPOINT 的参数。正是基于这样的原理,Docker 容器的启动进程为实际为 ENTRYPOINT,而不是 CMD。

需要注意的是,Dockerfile 里的指令并不都是只在容器内部的操作。就比如 ADD,它指的是把当前目录(即 Dockerfile 所在的目录)里的文件,复制到指定容器内的目录当中。

更多能在Dockerfile中使用的指令,可以参考官方文档:

https://docs.docker.com/engine/reference/builder/#dockerfile-reference。

根据前面的描述,现在我们的整个应用的目录结构应该如下这样:

$ ls
Dockerfile  app.py   requirements.txt

执行下面的指令可以构建镜像:

$ docker build  -f /path/to/Dockerfile -t helloworld .
Sending build context to Docker daemon  4.608kB
Step 1/7 : FROM python:3.6-alpine
 ---> 5e7f84829665
Step 2/7 : WORKDIR /app
 ---> Using cache
 ---> dbb4a00a8f68
Step 3/7 : ADD . /app
 ---> fd33ac91c6c7
Step 4/7 : RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
 ---> Running in 6b82e863d802
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting Flask
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f2/28/2a03252dfb9ebf377f40fba6a7841b47083260bf8bd8e737b0c6952df83f/Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting click>=5.1
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/dd/c0/4d8f43a9b16e289f36478422031b8a63b54b6ac3b1ba605d602f10dd54d6/click-7.1.1-py2.py3-none-any.whl (82 kB)
Collecting Jinja2>=2.10.1
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/27/24/4f35961e5c669e96f6559760042a55b9bcfcdb82b9bdb3c8753dbe042e35/Jinja2-2.11.1-py2.py3-none-any.whl (126 kB)
Collecting itsdangerous>=0.24
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Werkzeug>=0.15
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting MarkupSafe>=0.23
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz (19 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12629 sha256=1f965945354a52423078c573deb1a8116965e67b2467c3640264d7f02058b06d
  Stored in directory: /root/.cache/pip/wheels/06/e7/1e/6e3a2c1ef63240ab6ae2761b5c012b5a4d38e448725566eb3d
Successfully built MarkupSafe
Installing collected packages: click, MarkupSafe, Jinja2, itsdangerous, Werkzeug, Flask
Successfully installed Flask-1.1.2 Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.1 itsdangerous-1.1.0
Removing intermediate container 6b82e863d802
 ---> d672a00c1a2f
Step 5/7 : EXPOSE 8083
 ---> Running in b9b2338da3f3
Removing intermediate container b9b2338da3f3
 ---> e91da5a22e20
Step 6/7 : ENV NAME World
 ---> Running in d7e5d19f3eed
Removing intermediate container d7e5d19f3eed
 ---> 4f959f34d486
Step 7/7 : CMD ["python", "app.py"]
 ---> Running in 99a97bedace0
Removing intermediate container 99a97bedace0
 ---> 3bc3e537ebb7
Successfully built 3bc3e537ebb7
Successfully tagged helloworld:latest

其中,-t 的作用是给这个镜像加一个 Tag,即:起一个好听的名字。docker build 会自动加载当前目录下的 Dockerfile 文件,然后按照顺序执行Dockerfile文件中的指令。

上面的命令执行完成后,就生成了一个镜像。可以通过下面的指令查看:

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
helloworld          latest              3bc3e537ebb7        2 minutes ago       103MB

还可以通过 docker inspect helloworld:latest 查看镜像的元信息。

元信息中包含了镜像的全部信息,包括镜像的tag,构建时间,环境变量等。

如果镜像不再需要了,可以通过docker image rm删除镜像。

有了镜像,就可以通过下面的指令来运行镜像得到容器了。

$ docker run -p 8082:8082 helloworld
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:8082/ (Press CTRL+C to quit)

上面命令中,镜像名 helloworld 后面,什么都不用写,因为在 Dockerfile 中已经指定了 CMD。否则,我就得把进程的启动命令加在后面:

$ docker run -p 8082:8082 helloworld python app.py

从现在看,容器已经正确启动,我们使用curl命令通过宿主机的IP和端口号,来访问容器中的web应用。

$ curl http://0.0.0.0:8082/

Hello World!

主机名: 59b607239c3a

从输出中可以看到容器的ID,容器是基于哪个镜像的启动的,容器中的进程,容器的启动时间及端口映射情况,以及容器的名字。

使用docker inspect 59b607239c3a命令,可以查看容器的元数据,内容非常丰富。

2、k8s从宿主机私有镜像仓库中拉取镜像

2.1 搭建宿主机私有镜像仓库;
sudo docker pull registry
sudo docker run -d -p 5000:5000 -v $(pwd):/var/lib/registry --restart always --name registry registry:2

2.2 验证私有镜像仓库
curl http://127.0.0.1:5000/v2/_catalog

2.3 推送镜像到私有镜像仓库
重启docker服务使配置生效: systemctl restart docker
172.19.242.79 是宿主机ip
mac 配置路径: 工具栏–> docker –> Preferences –> Daemon –> basic –> Insecure registries 加上一行: 172.19.242.79:5000

sudo vim /etc/docker/daemon.json
  "insecure-registries" : [
    "172.19.242.79:5000"
  ],
  "debug" : true

2.4 推送到镜像仓库
sudo docker tag helloworld 172.19.242.79:5000/flaskhelloworld  # 标记本地镜像,将其归入某一仓库
sudo docker push 172.19.242.79:5000/flaskhelloworld   # 最开始 docker build -t 直接打入指定(远程)仓库可省去上一步
curl -X GET 172.19.242.79:5000/v2/_catalog

2.5 配置minikube 并重启
为了使得minikube 虚机中的k8s 能拉取到宿主机私有镜像 需要上述两项配置 –registry-mirror 和 –insecure-registry
sudo minikube start --driver=none --insecure-registry="172.19.242.79:5000" 	--image-mirror-country cn \
	--iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.15.1.iso  \
	--registry-mirror=https://你注册的aliyun加速地址.mirror.aliyuncs.com

2.6 部署镜像与开放服务接口
sudo kubectl create deployment flaskhelloworld --image=172.19.242.79:5000/flaskhelloworld
sudo kubectl expose deployment flaskhelloworld --type=LoadBalancer --port=6789 --target-port=8082 
sudo minikube service flaskhelloworld --url
#sudo kubectl port-forward flaskhelloworld-6b7695c6df-5hclc 8888:8082
		
#sudo kubectl create -f flaskhelloworld.yaml
#sudo kubectl describe pod flaskhelloworld-pod
#sudo kubectl port-forward flaskhelloworld-pod 8888:8080

#sudo kubectl run flaskhelloworld --image=172.19.242.79:5000/flaskhelloworld --port 3000
#sudo kubectl expose pod flaskhelloworld --name flaskhelloworld-http --type=LoadBalancer
#sudo minikube service flaskhelloworld-http

3、k8s 中 pod、service、ingress 网络架构分析

sudo minikube service flaskhelloworld
|-----------|-----------------|-------------|----------------------------|
| NAMESPACE |      NAME       | TARGET PORT |            URL             |
|-----------|-----------------|-------------|----------------------------|
| default   | flaskhelloworld |        6789 | http://172.19.242.79:30792 |
|-----------|-----------------|-------------|----------------------------|
????  正通过默认浏览器打开服务 default/flaskhelloworld...
????  http://172.19.242.79:30792

如何进行minikube部署本地镜像实践与k8s网络架构分析

每次访问的主机信息不一样,是因为我们 deployments 后,执行了 

kubectl scale -n default deployment flaskhelloworld --replicas=3

集群有3个pod

如何进行minikube部署本地镜像实践与k8s网络架构分析

在Kubernetes中,部署一个Deployment是无法对外进行访问的,就是别的应用程序要想访问部署的Deployment,找不到该怎么去访问,为什么这么讲,因为Deployment一般都是多副本部署的,有可能会分布在不同的节点之上,而且重建Pod IP也会变,重新发布一下也会改变,所以没有办法去固定去访问哪个Pod,即使固定了,其他的Pod也访问不了,要想做到多个Pod都去提供服务,前面就必须要加一个负载均衡,提供一个访问入口,只有访问这个统一入口,才能转发到后端多个Pod上,只要访问这个Cluster IP就能转发到后端的Pod上。

如何进行minikube部署本地镜像实践与k8s网络架构分析

Service

  • Service定义了Pod的逻辑集合和访问这个集合的策略

  • Service的引入为解决Pod的动态变化,提供了服务发现和负载均衡

  • 使用CoreDNS解析Service名称

sudo kubectl get services
NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
flaskhelloworld         LoadBalancer   10.98.106.240         6789:30792/TCP               31m
flink-jobmanager        ClusterIP      10.100.169.253           6123/TCP,6124/TCP,8081/TCP   7d12h
flink-jobmanager-rest   NodePort       10.103.71.37             8081:30424/TCP               7d12h
kubernetes              ClusterIP      10.96.0.1                443/TCP                      7d12h

因此,我们也可以用集群IP来访问:

如何进行minikube部署本地镜像实践与k8s网络架构分析

services 暴露出去之后,也就是需要让用户去访问,比如搭建一个电商网站,让用户去访问,Ingress相对于Service,是一个互补的状态,Service主要提供了集群内部的访问,也可以暴露一个TCP/UDP的端口,而Ingress主要是一个7层的转发,也就是提供一个统一的入口,只要访问Ingress Controller,就能帮你转发你部署所有的项目,也就是所有的项目都使用域名去访问。

如何进行minikube部署本地镜像实践与k8s网络架构分析

为了进一步了解网络架构,我们也可以直接用 pod ip + port 来访问

sudo kubectl get endpoints serviceName  # 查看 Service backend pods(在 Kubernetes 对应多个 endpoint)

如何进行minikube部署本地镜像实践与k8s网络架构分析

如何进行minikube部署本地镜像实践与k8s网络架构分析

如何进行minikube部署本地镜像实践与k8s网络架构分析

如何进行minikube部署本地镜像实践与k8s网络架构分析

看完上述内容,你们掌握如何进行minikube部署本地镜像实践与k8s网络架构分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程笔记行业资讯频道,感谢各位的阅读!


推荐阅读
author-avatar
手机用户2502891303_279
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有