利用 minikube 在 macOS 上部署一个 Go 程序
利用 minikube 在 macOS 上部署一个 Go 程序
ARCHIVE 这篇写于 2018 年,距今 8 年多了。里面的版本、链接和做法可能都已经过时,看的时候留个心眼。
本教程的目标是将一个简单的 Go 程序转换为在 Kubernetes 上运行的程序。
本教程将向你展示如何获取在计算机上开发的代码,将其转换为 Docker 容器映像,然后在 Minikube 上运行该映像。
Minikube 提供了一种在本地计算机上免费运行 Kubernetes 的简单方法。
目标
- 运行一个 Go 应用程序;
- 部署程序到 minikube;
- 查看程序日志;
- 更新程序镜像;
准备工作
使用 macOS 的用户,可以用 Homebrew 来安装 minikube。
注意:如果在将计算机更新到 macOS 10.13 后运行
brew update时看到以下 Homebrew 错误:
Error: /usr/local is not writable. You should change the ownership
and permissions of /usr/local back to your user account:
sudo chown -R $(whoami) /usr/local
你可以按照以上提示,也可以通过重装 Homebrew 来解决这个问题:
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
-
基于 Go 开发的简单程序;
-
安装 Docker,在 macOS 上,我们推荐 Docker for Mac.
创建一个 minikube 集群
本教程使用 Minikube 创建本地群集,本教程还假设你在 macOS 上使用 Docker for Mac。
如果你使用的是 Linux 之类的其他平台,或使用 VirtualBox 而不是 Docker for Mac,则安装 Minikube 的说明可能略有不同,有关 Minikube 的一般安装说明请参阅 Minikube 安装指南。
使用 Homebrew 安装最新的 Minikube 版本:
$ brew cask install minikube
安装 HyperKit 驱动,按照这里所描述的 Minikube driver installation guide
使用 Homebrew 下载 kubectl 命令行工具,你可以使用该工具与 Kubernetes 集群进行交互:
$ brew install kubernetes-cli
确定你是否可以在没有代理的情况下直接访问 https://cloud.google.com/container-registry/ 等网站,方法是打开新终端并使用:
$ curl --proxy "" https://cloud.google.com/container-registry/
确保已启动 Docker 守护程序,你可以使用以下命令确定 docker 是否正在运行:
$ docker images
如果不需要代理,请启动 Minikube 集群:
$ minikube start --vm-driver=hyperkit
如果需要代理服务器,请使用以下方法启动具有代理设置的 Minikube 集群:
$ minikube start --vm-driver=hyperkit --docker-env HTTP_PROXY=http://your-http-proxy-host:your-http-proxy-port --docker-env HTTPS_PROXY=http(s)://your-https-proxy-host:your-https-proxy-port
或者根据文档:,在 ~/.minikube/machines/minikube/config.json 修改 HostOptions.EngineOptions.Env 对应的 HTTP_PROXY 和 HTTPS_PROXY:
"Env": [
"HTTP_PROXY=http://192.168.1.8:1087",
"HTTPS_PROXY=http://192.168.1.8:1087",
"NO_PROXY=192.168.99.0/24"
],
然后再重新执行:
$ minikube start --vm-driver=hyperkit --bootstrapper=localkube
如果执行之后,长时间没有响应,可以 Ctrl-C 中断,然后再重试,如果还是不行那么你可以参照以下文章中所提到的方法去调试,应该就能解决了。
如果出现状态为 ContainerCreating 的,一般都是因为网络问题导致无法正常拉取镜像导致的。
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system kube-addon-manager-minikube 0/1 ContainerCreating 0 16m
如果你遇到墙的问题了,可能会有以下表象:
- minikube dashboard 长时间无响应;
- kubectl run xxx 长时间处于 ContainerCreating 等;
--vm-driver=hyperkit 标志指定你使用的是 Docker for Mac,
默认的 VM 驱动程序是 VirtualBox,需要你额外安装它。
现在设置 Minikube context,
context 决定了哪个集群的 kubectl 与之交互。
你可以在 ~/.kube/config 文件中查看所有可用的 context。
$ kubectl config use-context minikube
Switched to context "minikube".
验证 kubectl 是否与已配置的集群通信:
$ kubectl cluster-info
Kubernetes master is running at https://192.168.64.4:8443
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
在浏览器中打开 Kubernetes dashboard:
$ minikube dashboard
创建你的 Go 应用程序
下一步是编写程序,将代码保存在名为 minikube-hello-go 的文件夹中,文件名为 server.go :
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to minikube server!")
})
http.ListenAndServe(":8080", nil)
}
运行你的程序:
$ go run server.go
或者
$ go build
$ ./minikube-hello-go
你可以通过浏览器访问 http://localhost:8080/ 看到 Welcome to minikube server! 消息。
通过 Ctrl-C 来结束运行的 Go 服务。
下一步是将你的应用程序打包到 Docker 容器中。
创建一个 Docker 容器镜像
在 minikube-hello-go 文件夹中创建一个文件 Dockerfile。 用 Dockerfile 文件来描述你想构建的这个镜像。你可以基于一个已经存在的镜像来构建一个 Docker 容器镜像,在这个教程中,我们依赖 golang:1.10.3 镜像。
FROM golang:1.10.3
EXPOSE 8080
WORKDIR /go/src/server
COPY . .
RUN go install -v ./...
CMD [ "server" ]
这个 Docker 镜像的配方从 Docker 官方仓库中拉取 golang:1.10.3 镜像,公开端口 8080,将当前文件复制到镜像中的 /go/src/server/ 文件夹中,然后运行 go install 进行安装,然后启动服务器。
因为本教程使用 Minikube ,而不是将 Docker 镜像推送到仓库,所以你可以使用与 Minikube VM 相同的 Docker 主机来构建镜像,以便自动显示镜像,为此,请确保使用 Minikube Docker 守护程序:
$ eval $(minikube docker-env)
注意:当你稍候不再希望使用 Minikube 主机时,可以通过运行
eval $(minikube docker-env -u)撤消此更改。
使用 Minikube Docker 守护进程构建 Docker 镜像(注意最后的 .):
$ docker build -t hello-go:v1 .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-go v1 f9a6fbe2045d 13 minutes ago 801MB
现在,Minikube VM 可以运行你构建的映像。
创建一个 Deployment
Kubernetes Pod 是一个由一个或多个容器组成的组合,用于管理和联网。 本教程中的 Pod 只有一个 Container。 Kubernetes Deployment 会检查 Pod 的运行状况,并在 Pod 终止时重新启动 Pod 的容器。 Deployments 是管理 Pod 的创建和扩容的推荐方法。
使用 kubectl run 命令创建管理 Pod 的 Deployment。
Pod 根据你的 hello-go:v1 Docker 镜像运行一个 Container。
将 --image-pull-policy 标志设置为 Never 以永远使用本地映像,而不是从 Docker 仓库中提取它(因为你没有将其推送到那里):
$ kubectl run hello-go --image=hello-go:v1 --port=8080 --image-pull-policy=Never
查看 Deployment:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-go 1 1 1 1 40s
查看 Pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-go-648b9c5f5f-zdlnc 1/1 Running 0 1m
查看集群事件:
$ kubectl get events
LAST SEEN FIRST SEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
2m 2m 1 hello-go-648b9c5f5f-zdlnc.15468316fd9704a1 Pod Normal Scheduled default-scheduler Successfully assigned hello-go-648b9c5f5f-zdlnc to minikube
2m 2m 1 hello-go-648b9c5f5f.15468316fd36e46d ReplicaSet Normal SuccessfulCreate replicaset-controller Created pod: hello-go-648b9c5f5f-zdlnc
2m 2m 1 hello-go.15468316fc5d32bd Deployment Normal ScalingReplicaSet deployment-controller Scaled up replica set hello-go-648b9c5f5f to 1
2m 2m 1 hello-go-648b9c5f5f-zdlnc.1546831710495581 Pod Normal SuccessfulMountVolume kubelet, minikube MountVolume.SetUp succeeded for volume "default-token-5nndf"
2m 2m 1 hello-go-648b9c5f5f-zdlnc.1546831734d69b39 Pod spec.containers{hello-go} Normal Pulled kubelet, minikube Container image "hello-go:v1" already present on machine
2m 2m 1 hello-go-648b9c5f5f-zdlnc.1546831737b6f001 Pod spec.containers{hello-go} Normal Created kubelet, minikube Created container
2m 2m 1 hello-go-648b9c5f5f-zdlnc.154683173df5a719 Pod spec.containers{hello-go} Normal Started kubelet, minikube Started container
查看kubectl配置:
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority: /Users/xxxx/.minikube/ca.crt
server: https://192.168.64.3:8443
name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: /Users/xxxx/.minikube/client.crt
client-key: /Users/xxxx/.minikube/client.key
有关 kubectl 命令的更多信息,请参阅 kubectl 概述。
创建一个 Service
默认情况下,Pod 只能通过 Kubernetes 集群中的内部 IP 地址访问。要使 Kubernetes 虚拟网络外部可以访问 hello-go Container,你必须将 Pod 公开为 Kubernetes Service。
在你的开发机器上,你可以使用 kubectl expose 命令将 Pod 公开到公共网络:
$ kubectl expose deployment hello-go --type=LoadBalancer
查看你刚刚创建的 Service:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-go LoadBalancer 10.107.111.2 <pending> 8080:32056/TCP 1s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12h
--type=LoadBalancer 标志表示你要在集群外部公开服务。在支持负载均衡的云提供商上,将配置外部 IP 地址以访问服务。
在 Minikube 上,LoadBalancer 类型通过 minikube service 命令使服务可访问。
$ minikube service hello-go
Opening kubernetes service default/hello-go in default browser...
这将使用为你的应用程序提供服务的本地 IP 地址自动打开浏览器窗口,并显示 Welcome to minikube server! 消息。
假设你已使用浏览器或 curl 向新 Web 服务发送请求,你现在应该能够看到一些日志:
$ kubectl logs -f <pod-name>
更新你的应用程序
编辑 server.go 文件以返回新消息:
fmt.Fprintf(w, "Welcome to minikube go server v2!")
构建新版本的镜像(注意最后的 .):
$ docker build -t hello-go:v2 .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-go v2 f37ea6b3ca9b 15 hours ago 801MB
hello-go v1 41e419790e7d 15 hours ago 801MB
更新 Deployment 的镜像:
$ kubectl set image deployment/hello-go hello-go=hello-go:v2
或者直接修改 deployment/hello-go 的文件:
$ kubectl edit deployment/hello-go
使用浏览器或者 curl 查看运行结果,发现显示内容也已经更新了。
或者你也可以使用 minikube service hello-node ,他会自动打开浏览器并加载网址显示信息。
启用插件
Minikube 有一组内置插件,可以在本地 Kubernetes 环境中启用,禁用和打开。
首先列出当前支持的插件:
$ minikube addons list
- addon-manager: enabled
- coredns: disabled
- dashboard: enabled
- default-storageclass: enabled
- efk: disabled
- freshpod: disabled
- heapster: enabled
- ingress: disabled
- kube-dns: enabled
- metrics-server: disabled
- nvidia-driver-installer: disabled
- nvidia-gpu-device-plugin: disabled
- registry: disabled
- registry-creds: disabled
- storage-provisioner: enabled
必须运行 Minikube 才能使这些命令生效。 要启用 heapster 插件,例如:
$ minikube addons enable heapster
heapster was successfully enabled
查看刚刚创建的 Pod 和 Service:
$ kubectl get po,svc -n kube-system
NAME READY STATUS RESTARTS AGE
pod/heapster-gb7jj 1/1 Running 0 10h
pod/influxdb-grafana-m5ltj 2/2 Running 0 10h
pod/kube-addon-manager-minikube 1/1 Running 0 13h
pod/kube-dns-6dcb57bcc8-g6q9w 3/3 Running 0 10h
pod/kubernetes-dashboard-5498ccf677-p92sz 1/1 Running 0 10h
pod/storage-provisioner 1/1 Running 0 10h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/heapster ClusterIP 10.101.28.158 <none> 80/TCP 10h
service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 10h
service/kubernetes-dashboard NodePort 10.107.13.248 <none> 80:30000/TCP 10h
service/monitoring-grafana NodePort 10.110.220.73 <none> 80:30002/TCP 10h
service/monitoring-influxdb ClusterIP 10.107.27.163 <none> 8083/TCP,8086/TCP 10h
打开端点以在浏览器中与 heapster 进行交互:
$ minikube addons open heapster
Opening kubernetes service kube-system/monitoring-grafana in default browser...
可能你打开查看监控是没有数据的,你可以模拟访问请求,然后再查看监控的 dashboard。
$ while sleep 0.1; do curl http://192.168.64.3:32056/; done
如果你要关闭 heapster:
$ minikube addons disable heapster
heapster was successfully disabled
heapster 的完全关闭需要等一段时间。
清理
现在,你可以清理在群集中创建的资源:
$ kubectl delete service hello-go
service "hello-go" deleted
$ kubectl delete deployment hello-go
deployment.extensions "hello-go" deleted
(可选)强制删除创建的 Docker 镜像:
$ docker rmi hello-go:v1 hello-go:v2 -f
docker rmi hello-go:v1 hello-go:v2 -f
Untagged: hello-go:v1
Deleted: sha256:41e419790e7da55ac34456c09e921f2d9dfa336aab6a47a67079746a8428ae4e
...
Untagged: hello-go:v2
Deleted: sha256:f37ea6b3ca9bb06496751be9e93e50456a49363707606625b85b3811a663c364
...
(可选)停止 Minikube VM:
$ minikube stop
$ eval $(minikube docker-env -u)
eval $(minikube docker-env -u) 这个非常重要,如果你没有执行这个的话,你本地的 docker 运行会执行到 minikube 上的 vm ;
(可选)删除 Minikube VM:
$ minikube delete
其他问题
Error restarting cluster: restarting kube-proxy: waiting for kube-proxy to be up for configmap update: timed out waiting for the condition
这个原因很可能是有 minikube 旧版本导致的,你可以执行 minikube delete,然后再执行 minikube start
Error starting host: Error creating new host: Driver "hyperkit" not found. Do you have the plugin binary "docker-machine-driver-hyperkit" accessible in your PATH?
从 RELEASE 上下载,然后将其移动到 /usr/local/bin/ 目录下;
还需要执行以下命令,给予权限:
$ sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit && sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit
然后再运行:minikube start --vm-driver=hyperkit --bootstrapper=localkube --docker-env HTTP_PROXY=http://127.0.0.1:1087 --docker-env HTTPS_PROXY=http://127.0.0.1:1087 即可(--docker-env 可要可不要)。
参考资料
茶歇驿站
一个可以让你停下来看一看,在茶歇之余给你帮助的小站,这里的内容主要是后端技术,个人管理,团队管理,以及其他个人杂想。