9

再见Docker Desktop,你好 Minikube!

 2 years ago
source link: http://dockone.io/article/2434628
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

我使用Docker Desktop在Mac中启用Docker和Kubernetes已经有一段时间了。尽管它疯狂地吞噬着CPU和内存,让粉丝们疯狂。但随着"当面 "弹出强制升级Docker的弹窗和软件许可的变更,是时候为本地Kubernetes开发寻找其他替代品了。
这篇文章只会专注于Mac平台。如果你在Linux上尝试过,请告诉我情况如何。

卸载Docker Desktop

让我们先从删除Docker Desktop开始。
brew uninstall docker

这不仅会摆脱Docker,但也会摆脱Hyperkit以及Docker守护进程。Docker守护进程允许我们构建镜像并适用交互式的Docker CLI与之对话。当然还包括Kubernetes集群和kubectl二进制(除非你有单独部署)。如果你没有使用Homebrew,那么就需要相应地卸载这些工具。
然后,让我们把这些工具逐一找回来。

安装Hyperkit

Hyperkit仍然是在Mac上本地运行Kubernetes集群的一个可行的选择,我们先来安装它,
brew install hyperkit

确认安装正确,
$ hyperkit -v
hyperkit: 0.20200908Homepage:https://github.com/docker/hyperkit
License: BSD

安装Docker CLI

我们是想摆脱Docker Desktop,但并不是Docker本身。Docker仍然是一个很有用的、开源的容器管理工具,如果你有一堆Dockerfiles需要处理,Docker CLI会很有用。
brew install docker

注意:千万不要运行brew install --cask docker。这会安装Docker Desktop集成版本,我们又要重头来过。

这仅仅会安装Docker CLI,但不会安装Docker守护程序dockerd。你可以通过运行docker info看到这一点。
$ docker info
Client:
Context:    default
Debug Mode: falseServer:
ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

安装Kubectl

brew install kubectl

这一点没什么可说的。

安装Minikube (和Docker守护进程)

随着Hyperkit的部署,我们已经准备好部署Kubernetes集群了。并且,在这个过程中启动了一个Docker守护程序。
brew install minikube

在我们开始使用Kubernetes集群之前,这里有一些小知识需要了解。

使用哪一种驱动?

换句话说,我们是将Kubernetes部署在虚拟机、容器还是直接部署在裸金属服务器上?根据操作系统的不同,这里有多种选择。我们将使用Mac的Hyperkit驱动。

使用哪一种容器运行时?

可用的选项 - docker、containerd和cri-o。鉴于Kubernetes本身正在远离Docker而转向Containerd,Containerd是一个不错的选择。但由于我们希望Docker守护程序能够构建docker镜像,所以我们还是使用Docker吧。

设定CPU和内存限制

和Docker Desktop一样,设置正确的CPU和内存限制总是明智,特别是如果你打算运行许多pod。
minikube config set cpus 6
minikube config set memory 12g

最后,启动Kubernetes集群,
$ minikube start --kubernetes-version=v1.19.14 --driver=hyperkit --container-runtime=docker

使用命令行选项-kubernetes-version来部署特定版本的Kubernetes。不用这个标志的话,默认部署最新的版本。我需要部署一个较早的版本来满足我的需要。
以下是上述命令的输出,
minikube v1.23.0 on Darwin 11.5.2
▪ MINIKUBE_ACTIVE_DOCKERD=minikube
  Using the hyperkit driver based on user configuration
  Starting control plane node minikube in cluster minikube
  Downloading Kubernetes v1.19.14 preload ...
> preloaded-images-k8s-v12-v1...: 470.78 MiB / 470.78 MiB  100.00% 6.17 MiB
  Creating hyperkit VM (CPUs=6, Memory=12288MB, Disk=20000MB) ...
  This VM is having trouble accessinghttps://k8s.gcr.io
  To pull new external images, you may need to configure a proxy:https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
  Preparing Kubernetes v1.19.14 on Docker 20.10.8 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
  Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
  Enabled addons: storage-provisioner, default-storageclass❗  /usr/local/bin/kubectl is version 1.22.1, which may have incompatibilites with Kubernetes 1.19.14.
▪ Want kubectl v1.19.14? Try 'minikube kubectl -- get pods -A'
  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

如果你在本地运行dnsmasq,在集群中可能会出现DNS解析失败。你可以卸载它或者在dnsmasq.conf中添加listen-address=192.168.64.1。更多信息可以在这里找到。

Kube Config的上下文已经设置好了。我们可以用 kubectl来检查集群,如下所示,
$ minikube kubectl get nodes
NAME       STATUS   ROLES    AGE    VERSION
minikube   Ready    master   7m6s   v1.19.14

由于我们已经安装了kubectl二进制程序,我们可以直接使用它。
此时,我们已经有了一个Kubernetes集群,由于我们使用了Docker驱动,Docker守护程序也在运行。所以在我们使用守护进程之前,让我们先设置环境变量。
eval $(minikube docker-env)

确认docker守护进程是正常工作的,
$ docker info
Client:
Context:    default
Debug Mode: falseServer:
Containers: 14
Running: 14
Paused: 0
Stopped: 0
Images: 10
Server Version: 20.10.8
Storage Driver: overlay2
Backing Filesystem: extfs
...

下面是我们的Minikube集群在K9S中的样子。
新安装的Minikube集群的K9S截图,
https://miro.medium.com/max/2000/1*K4FCX7goEtekfksg9ZOGdA.png

需要Docker Compose?

用以下命令安装Docker-Compose
brew install docker-compose

暴露Services到Minikube外部

对于本地开发,通常是通过浏览器或CLI从电脑访问服务。端口转发总是一个选择,但有时Ingress或负载均衡器也是有用的。让我们看看它们是如何与Minikube一起工作的。

处理Ingress资源

我们现在有了一个Kubernetes集群,也可以在上面部署应用程序。但我们如何访问Ingress资源呢?Minikube有一个答案,就是addons(附加组件)。
$ minikube addons enable ingress
▪ Using image k8s.gcr.io/ingress-nginx/controller:v1.0.0-beta.3
▪ Using image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0
▪ Using image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0
Verifying ingress addon...


这会部署Nginx Ingress控制器。更重要的是,它会把Nginx服务部署以 NodePort的形式部署,并将Minikube的IP直接指向Ingress。让我们先找到这个IP,
$ minikube ip
192.168.64.12


我们在80端口调用上述IP,我们应该可以从Nginx得到响应,
$ curl http://192.168.64.12
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>


记住,Ingress依赖于DNS工作,它应该被解析到Minikube的IP上。如果后端服务之一调用该DNS,除非明确配置了,否则会解析失败。这个时候,另一个附加组件可以来拯救你!
$ minikube addons enable ingress-dns
▪ Using image cryptexlabs/minikube-ingress-dns:0.3.0


这将在Kubernetes集群内启动一个DNS服务器,监听在Minikube的IP上。此外,还需要一个自定义的解析器,以强制自定义顶级域名(如.test,不要使用.local)的DNS解析被重定向到上面启动的DNS服务器。Minikube Ingress DNS文档很好地解释了这一点。按照文档里描述的步骤操作,你将会部署成功一个带有自定义DNS的Ingress。

负载均衡类型的Service

部署负载均衡器类型的服务,并从主机上访问它,就像你在云端部署时一样,这不是很好吗?多亏了 metalb插件,让这变得很简单。
minikube addons enable metallb


这将部署另外两个pod,负责为负载均衡器类型的Service分配一个外部IP。如果不这样做,这些服务的外部IP将始终处于"pending"状态。

在使用metallb之前,还有一个步骤。默认情况下,metallb没有办法知道哪个范围的IP可以分配给负载均衡器的服务。运行下面的命令来提供一个范围。
$ minikube addons configure metallb
-- Enter Load Balancer Start IP: 192.168.64.5
-- Enter Load Balancer End IP: 192.168.64.15
▪ Using image metallb/speaker:v0.9.6
▪ Using image metallb/controller:v0.9.6
metallb was successfully configured


基于你的Minikube IP,分配一个小范围的IP,包括Minikube IP。现在,每当你部署一个负载均衡器服务时,这个范围内的一个IP将被分配。

登录到远程镜像仓库

你可能仍然有旧的 ~/.docker/config.json,其中 credsStore设置为 osxkeychaindesktop。这在新的配置中不会起作用。为了解决这个问题,我们来安装 Docker Credential Helper
brew install docker-credential-helper


密钥凭证还是会像以前一样存储在MacOS Keychain中。如果这不起作用,一个快速的解决方法是删除 ~/.docker/config.json文件,然后再次登录到镜像仓库。

保留Docker镜像和持久化存储卷声明

Added 7th Sept 2021

Docker Desktop的一个好处是,你可以关闭Kubernetes集群,以后再启动它,用相同的Docker镜像和持久化卷运行你的pod。例如,在Kubernetes中运行本地数据库时,这就很有用。能够在多次重启中仍然保持有效的持久化卷是很方便的。
在Minikube中,如果我用 minikube stop关闭集群(和Hyperkit虚拟机),它会删除Docker镜像和所有持久化卷,这很麻烦。但幸运的是,Minikube提供了一种防止删除的方法。我们可以暂停Kubernetes集群和Hyperkit VM,而不是停止它。
minikube pause

该命令会终止Kubernetes集群,但不会删除Hyperkit虚拟机。这就释放了更多的CPU,同时仍然保留了所有的Docker镜像和持久化卷。但是,等一下,它变得更好!它不会停止dockerd守护进程。所以你可以继续使用Docker CLI,只是别忘了用 eval $(minikube docker-env)设置一下docker环境。
当你想恢复在Kubernetes集群上的工作时,可以运行以下命令。
minikube unpause

而你将拥有所有的系统Pod,包括附加组件Addons。这甚至在笔记本电脑重新启动后,也能正常工作!

在Docker容器中绑定挂载

Added 7th Sept 2021

一些在Reddit上的好心人指出,Docker容器中的绑定挂载 (-v)在Minikube和Docker的配置中并不能工作。这是Docker容器的一个常见操作,他理论上应该可以正常工作。
由于存在Hyperkit作为中间层,挂载一个卷其实是分成两步操作的。首先,让我们把笔记本上的磁盘挂载到Hyperkit VM上。
minikube mount /myvolume:/test

这将把本地文件夹 /myvolume挂载到Hyperkit VM的 /test路径下。这个进程仍然是活跃的,所以你不应该关闭这个终端。
在另一个终端上,运行Docker容器,并将 /test卷绑定到容器内的一个路径上。
docker run --rm -it -v /test:/inside busybox /bin/sh

这将在容器内的Hyperkit VM上挂载 /test卷,路径为 /inside。实际上,这会使得笔记本电脑上 /myvolume下的所有处在容器内的文件和文件夹处于读写模式。很好!

在周日下午花了几个小时后,我对这个新的配置相当满意。我们摆脱了Docker Desktop,用Hyperkit和Minikube取代了它。我们仍然可以使用Docker API来管理Docker文件,并在本地Kubernetes集群中部署应用程序。最重要的是,我的笔记本可以愉快地运行,额外的资源可以用来运行Slack、Notion和其他Electron应用程序;-)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK