您好,登錄后才能下訂單哦!
如何進行minikube部署本地鏡像實踐與k8s網絡架構分析,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
在 windows10 的 WSL2 里用minikube搭建了一個k8s環境,但是每次拉取鏡像都很慢甚至失敗(原因大家都懂的), 本文的方案的原理是, 先將鏡像在宿主機上f-q拉取到本地, 再由minikube 虛機中的k8s 來拉取本地鏡像, 這樣即可解決之前的拉取鏡像失敗,也可提升拉取鏡像的速度;
兩種方案
把私有鏡像倉庫docker registry 搭建在宿主機上, k8s從本地宿主機上拉取鏡像;
把本地鏡像推送到minikube的私有鏡像倉庫上, k8s從minikube的私有鏡像倉庫(k8s的本地私有鏡像倉庫)拉取鏡像;
一個完整鏡像通常包含應用本身和操作系統,當然還包含需要的依賴軟件。
首先準備一個應用。新建一個本文文件,起名叫 app.py,寫入下面的內容,實現一個簡單的web應用:
from flask import Flask import socket import os app = Flask(__name__) @app.route('/') def hello(): html = "<h4>Hello {name}!</h4>" \ "<b>主機名:</b> {hostname}<br/>" 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/ <h4>Hello World!</h4><b>主機名:</b> 59b607239c3a<br/>
從輸出中可以看到容器的ID,容器是基于哪個鏡像的啟動的,容器中的進程,容器的啟動時間及端口映射情況,以及容器的名字。
使用docker inspect 59b607239c3a命令,可以查看容器的元數據,內容非常豐富。
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
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
每次訪問的主機信息不一樣,是因為我們 deployments 后,執行了
kubectl scale -n default deployment flaskhelloworld --replicas=3
集群有3個pod
在Kubernetes中,部署一個Deployment是無法對外進行訪問的,就是別的應用程序要想訪問部署的Deployment,找不到該怎么去訪問,為什么這么講,因為Deployment一般都是多副本部署的,有可能會分布在不同的節點之上,而且重建Pod IP也會變,重新發布一下也會改變,所以沒有辦法去固定去訪問哪個Pod,即使固定了,其他的Pod也訪問不了,要想做到多個Pod都去提供服務,前面就必須要加一個負載均衡,提供一個訪問入口,只有訪問這個統一入口,才能轉發到后端多個Pod上,只要訪問這個Cluster IP就能轉發到后端的Pod上。
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 <pending> 6789:30792/TCP 31m flink-jobmanager ClusterIP 10.100.169.253 <none> 6123/TCP,6124/TCP,8081/TCP 7d12h flink-jobmanager-rest NodePort 10.103.71.37 <none> 8081:30424/TCP 7d12h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d12h
因此,我們也可以用集群IP來訪問:
services 暴露出去之后,也就是需要讓用戶去訪問,比如搭建一個電商網站,讓用戶去訪問,Ingress相對于Service,是一個互補的狀態,Service主要提供了集群內部的訪問,也可以暴露一個TCP/UDP的端口,而Ingress主要是一個7層的轉發,也就是提供一個統一的入口,只要訪問Ingress Controller,就能幫你轉發你部署所有的項目,也就是所有的項目都使用域名去訪問。
為了進一步了解網絡架構,我們也可以直接用 pod ip + port 來訪問
sudo kubectl get endpoints serviceName # 查看 Service backend pods(在 Kubernetes 對應多個 endpoint)
看完上述內容,你們掌握如何進行minikube部署本地鏡像實踐與k8s網絡架構分析的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。