1.创建、运行及共享容器镜像
首先,需要在Linux主机上安装Docker。如果使用的不是Linux操作系统,就需要启动Linux虚拟机(VM)并在虚拟机中运行Docker。如果使用的是Mac或Windows系统,Docker将会自己启动一个虚拟机并在虚拟机中运行Docker守护进程。Docker客户端可执行文件可以在宿主操作系统中使用,并可以与虚拟机中的守护进程通信。
PS C:\Users\Administrator> docker run busybox echo "hello docker"
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
205dae5015e7: Pull complete
Digest: sha256:7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c
Status: Downloaded newer image for busybox:latest
hello docker
1.1创建一个简单的 Node.js 应用
nodejs服务器:
const http = require('http');
const os = require('os');
console.log("myapp 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);
FROM node:7
ADD app.js ./app.js
ENTRYPOINT ["node", "app.js"]l
E:\code\docker\node>docker build -t myapp -f ./DockerfIle .
[+] Building 171.0s (7/7) FINISHED
...
运行容器:
docker run --name myapp -p 8080:8080 -d myapp
这条命令告知Docker基于myapp镜像创建一个叫myapp的新容器。这个容器与命令行分离(-d标志),这意味着在后台运行。本机上的8080端口会被映射到容器内的8080端口(-p8080:8080选项),所以可以通过http://localhost:8080访问这个应用。
查看真正运行的容器:
E:\code\docker>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
87a051786b6c myapp "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp myapp
1715f91e7475 kindest/node:v1.24.0 "/usr/local/bin/entr…" 5 months ago Up 19 minutes
dev-worker
df4edbc9246a kindest/node:v1.24.0 "/usr/local/bin/entr…" 5 months ago Up 19 minutes
dev-worker2
8a57dda6aa9b kindest/node:v1.24.0 "/usr/local/bin/entr…" 5 months ago Up 19 minutes 127.0.0.1:2949->6443/tcp dev-control-plane
访问容器内服务:
dockerps只会展示容器的大部分基础信息。可以使用dockerinspect查看更多的信息:
docker inspect myapp
容器拥有完整的文件系统:
E:\code\docker>docker exec -it myapp bash
root@87a051786b6c:/# ls
app.js bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
这会在已有的myapp容器内部运行bash。bash进程会和主容器进程拥有相同的命名空间。这样可以从内部探索容器,查看Node.js和应用是如何在容器里运行的。-it选项是下面两个选项的简写:-i,确保标准输入流保持开放。需要在shell中输入命令。-t,分配一个伪终端(TTY)。如果希望像平常一样使用shell,需要同时使用这两个选项(如果缺少第一个选项就无法输入任何命令。如果缺少第二个选项,那么命令提示符不会显示,并且一些命令会提示TERM变量没有设置)。
1.2 构建镜像
打包成镜像:
PS C:\Users\Administrator> docker tag myapp wallace2504/nodejs-app
PS C:\Users\Administrator> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myapp latest d8dc085fb4f4 14 minutes ago 660MB
wallace2504/nodejs-app latest d8dc085fb4f4 14 minutes ago 660MB
上传到镜像仓库:
PS C:\Users\Administrator> docker push wallace2504/nodejs-app
Using default tag: latest
The push refers to repository [docker.io/wallace2504/nodejs-app]
e979efccacfd: Pushed
ab90d83fa34a: Mounted from library/node
8ee318e54723: Mounted from library/node
e6695624484e: Mounted from library/node
da59b99bbd3b: Mounted from library/node
5616a6292c16: Mounted from library/node
f3ed6cb59ab0: Mounted from library/node
654f45ecb7e3: Mounted from library/node
2c40c66f7667: Mounted from library/node
latest: digest: sha256:182ac2e573c9535e101ffd3f59a7c9660ef6881ce5a21a77750198e74646ec18 size: 2213
镜像仓库:https://hub.docker.com/u/wallace2504
通过镜像仓库创建容器:
PS C:\Users\Administrator> docker run --name myapp2 -p 8081:8080 -d wallace2504/nodejs-app
7696bc323ab71d7b11f926dfa2e9f6d99b670234d3d79ab2dc06d04cb0d41267
2.配置Kubernetes集群
使用Minikube是运行Kubernetes集群最简单、最快捷的途径。 Minikube是一个构建单节点集群的工具,对于测试Kubernetes和本地开 发应用都非常有用。
2.1 使用minikube
使用Minikue启动一个Kubernetes集群:
PS C:\Users\Administrator> minikube start
😄 Microsoft Windows 11 Pro 10.0.22000 Build 22000 上的 minikube v1.26.1
🆕 Kubernetes 1.24.3 is now available. If you would like to upgrade, specify: --kubernetes-version=v1.24.3
🎉 minikube 1.29.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.29.0
💡 To disable this notice, run: 'minikube config set WantUpdateNotification false'
✨ 根据现有的配置文件使用 docker 驱动程序
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
🔄 Restarting existing docker container for "minikube" ...
🐳 正在 Docker 20.10.17 中准备 Kubernetes v1.23.8…
🔎 Verifying Kubernetes components...
▪ Using image registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
PS C:\Users\Administrator> kubectl
>> ^C
PS C:\Users\Administrator> minikube start
😄 Microsoft Windows 11 Pro 10.0.22000 Build 22000 上的 minikube v1.26.1
🆕 Kubernetes 1.24.3 is now available. If you would like to upgrade, specify: --kubernetes-version=v1.24.3
使用kubectl列出集群节点,要查看关于对象的更详细的信息,可以使用 kubectl describe 命令, 它显示了更多信息:
PS C:\Users\Administrator> kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane,master 177d v1.23.8
PS C:\Users\Administrator> kubectl describe node minikube
Name: minikube
Roles: control-plane,master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=minikube
kubernetes.io/os=linux
minikube.k8s.io/commit=62e108c3dfdec8029a890ad6d8ef96b6461426dc
minikube.k8s.io/name=minikube
minikube.k8s.io/primary=true
minikube.k8s.io/updated_at=2022_08_17T21_53_36_0700
minikube.k8s.io/version=v1.26.1
node-role.kubernetes.io/control-plane=
node-role.kubernetes.io/master=
node.kubernetes.io/exclude-from-external-load-balancers=
Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Wed, 17 Aug 2022 21:53:33 +0800
Taints: <none>
Unschedulable: false
...
2.2 在Kubernetes上运行第一个应用
部署应用程序最简单的方式是使用 kubectl run 命令,该命令可以创 建所有必要的组件而无需JSON或YAML文件:
PS C:\Users\Administrator> kubectl run myapp --image=wallace2504/nodejs-app --port=8080
pod/myapp created
#注意:kubectlrun在旧版本中默认创建的是deployment,但在新的版本中创建的是pod则其创建过程不涉及deployment
建议使用
kubectl create deployment myapp --image=wallace2504/nodejs-app
查看运行的应用:
PS C:\Users\Administrator> kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 105s
为了更好地理解容器、pod和节点之间的关系,请查看图 2.5。如你 所见,每个pod都有自己的IP,并包含一个或多个容器,每个容器都运 行一个应用进程。pod分布在不同的工作节点上。
查看pod详细信息:
PS C:\Users\Administrator> kubectl describe pod myapp
Name: myapp
Namespace: default
Priority: 0
Node: minikube/192.168.49.2
Start Time: Sat, 11 Feb 2023 16:34:05 +0800
Labels: run=myapp
Annotations: <none>
Status: Running
IP: 172.17.0.3
IPs:
IP: 172.17.0.3
Containers:
myapp:
Container ID: docker://accf5662760d75d7c7fe95c545c6ad14fac365458862558ad134fe544f3d63dd
Image: wallace2504/nodejs-app
Image ID: docker-pullable://wallace2504/nodejs-app@sha256:182ac2e573c9535e101ffd3f59a7c9660ef6881ce5a21a77750198e74646ec18
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 11 Feb 2023 16:34:29 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2tdqq (ro)
...
它显示了在Kubernetes中运行容器镜像所必需的两个步骤。首先,构建镜像并将其推送到DockerHub。这是必要的,因为在本地机器上构建的镜像只能在本地机器上可用,但是需要使它可以访问运行在工作节点上的Docker守护进程。
当运行kubectl命令时,它通过向KubernetesAPI服务器发送一个RESTHTTP请求,在集群中创建一个新的Deployment对象。然后,Deployment创建了一个新的pod,调度器将其调度到一个工作节点上。Kubelet看到pod被调度到节点上,就告知Docker从镜像中心中拉取指定的镜像,因为本地没有该镜像。下载镜像后,Docker创建并运行容器。
如何访问正在运行的pod?我们提到过每个pod都有自己的IP地址,但是这个地址是集群内部的,不能从集群外部访问。要让pod能够从外部访问,需要通过服务对象公开它,要创建一个特殊的LoadBalancer类型的服务。因为如果你创建一个常规服务(一个ClusterIP服务),比如pod,它也只能从集群内部访问。通过创建LoadBalancer类型的服务,将创建一个外部的负载均衡,可以通过负载均衡的公共IP访问pod。
#注意Minikube不支持LoadBalancer类型的服务,因此服务不会有外部IP。
老版本创建service流程:
在minikube中创建sercvice:
PS C:\Users\Administrator> kubectl expose pods myapp --type=NodePort --port=8080 --name myapp2
service/myapp2 exposed
PS C:\Users\Administrator> minikube service myapp2 --url
http://127.0.0.1:6249
❗ Because you are using a Docker driver on windows, the terminal needs to be open to run it.
或者直接暴露对外端口(不创建service):
PS C:\Users\Administrator> kubectl port-forward --address 0.0.0.0 myapp 8082:8080
Forwarding from 0.0.0.0:8082 -> 8080
获取service:
PS C:\Users\Administrator> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 178d
myapp2 NodePort 10.110.238.163 <none> 8080:32627/TCP 14m
为什么需要服务系统的第三个组件是http服务。要理解为什么需要服务,需要学习有关pod的关键细节。
pod的存在是短暂的,一个pod可能会在任何时候消失,或许因为它所在节点发生故障,或许因为有人删除了pod,或者因为pod被从一个健康的节点剔除了。当其中任何一种情况发生时,如前所述,消失的pod将被deployment替换为新的pod。新的pod与替换它的pod具有不同的IP地址。这就是需要服务的地方——解决不断变化的podIP地址的问题,以及在一个固定的IP和端口对上对外暴露多个pod。
当一个服务被创建时,它会得到一个静态的IP,在服务的生命周期中这个IP不会发生改变。客户端应该通过固定IP地址连接到服务,而不是直接连接pod。服务会确保其中一个pod接收连接,而不关心pod当前运行在哪里(以及它的IP地址是什么)。
2.3 水平伸缩应用
使用scale命令:
kubectl scale deployment myapp4 --replicas=3
#使用run命令创建的pod在新版本无法使用scale操作
2.4 Kubernetes dashboard
PS C:\Users\Administrator> minikube dashboard
🔌 正在开启 dashboard ...
▪ Using image registry.cn-hangzhou.aliyuncs.com/google_containers/dashboard:v2.6.0
▪ Using image registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-scraper:v1.0.8
🤔 正在验证 dashboard 运行情况 ...
🚀 Launching proxy ...
🤔 正在验证 proxy 运行状况 ...
PS C:\Users\Administrator> ^C
PS C:\Users\Administrator> minikube dashboard
🤔 正在验证 dashboard 运行情况 ...
🚀 Launching proxy ...
🤔 正在验证 proxy 运行状况 ...
🎉 Opening http://127.0.0.1:8033/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...