Skip to content

kubernetes 环境搭建之 minikube for Debian

官方文档:https://minikube.sigs.k8s.io/docs/start/

minikube 下载

shell
# 可访问 github 下载最新版本
curl -LO https://github.com/kubernetes/minikube/releases/download/v1.38.1/minikube_latest_amd64.deb

# 安装
sudo dpkg -i minikube_latest_amd64.deb

# 可选择移除安装包
rm -rf minikube_latest_amd64.deb

# 检查安装
minikube version

启动 minikube

注意:每次开机都需要运行 minikube start 命令来启动。

shell
# 非 root 用户启动,需要把当前用户添加到 docker 用户组
sudo usermod -aG docker $USER
newgrp docker

# 若是以 root 用户启动,则需要添加 --force 参数。
#minikube start --force

# 启动(会拉取镜像,但国内 docker hub 会有网络问题)
# 从而,安装过程会转向从 github 拉取 kicbase-v0.0.50-amd64.tar 包。
# ,而 github 也不稳定,可以多试几次
minikube start
# 加 --alsologtostderr 参数打印详细日志
minikube start --alsologtostderr

# 解决方案一:
# 从加速地址直接拉取镜像(注意:版本可能不同,可根据日志信息修改)
docker pull kicbase/stable:v0.0.50

# 解决方案二:
# 多尝试若干次后,直到出现下面信息:
# Downloading: https://github.com/kubernetes/minikube/releases/download/v1.38.1/kicbase-v0.0.50-amd64.tar -> /home/aday/.minikube/cache/kic/amd64/stable_v0.0.50.tar
# 此时如果网速可以,那就等它下载完(大约 1.3GB),如果很慢,可以直接去 github 链接下载,然后 SFTP 上传到上面指定的缓存位置。

# 安装成功出现:
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

# 安装完毕后,在命令行输入以下命令来验证是否安装成功。
minikube status

# 停止 minikube
minikube stop

# 此命令会删除所有 minikube 资源。即:需要重新 minikube start
minikube delete --all --purge

使用 minikube 自带的 kubuctl

shell
# 第一次运行会下载并初始化 kubectl(如果网络问题失败,可多尝试几次)
minikube kubectl -- get pods -A

# 实在下载不下来可通过 `sudo apt install kubectl` 直接安装 kubectl 命令。具体安装教程参考下一章节。

# 临时增加别名,就可以不用单独安装 kubectl 了
alias kubectl="minikube kubectl --"
# 永久增加别名
echo 'alias kubectl="minikube kubectl --"' >> ~/.bashrc
# 立即生效
source ~/.bashrc

# 验证安装是否成功
kubectl version --client

# 这样查询
kubectl get po -A

安装 kubectl

bash
sudo apt update
sudo apt install -y kubectl

# 卸载
sudo apt remove --purge kubectl -y

启动 dashboard

bash
# dashboard 需要启用 metrics-server
minikube addons enable metrics-server

# 打开 Kubernetes dashboard。使用 --alsologtostderr 参数打印详细日志
minikube dashboard --url --alsologtostderr

# 会由于拉取镜像问题出现 ImagePullBackOff 的问题导致 dashboard 无法正常启动。
# 1. 查看Dashboard相关 Pod 的详细状态
kubectl get pods -n kubernetes-dashboard
# 2. 描述具体出错的Pod,获取事件详情
kubectl describe pod <pod-name> -n kubernetes-dashboard
# 示例
kubectl describe pod dashboard-metrics-scraper-5565989548-8lj25 -n kubernetes-dashboard
kubectl describe pod kubernetes-dashboard-b84665fb8-wsm6v -n kubernetes-dashboard

# 可以找到所需要的镜像:
# docker.io/kubernetesui/metrics-scraper:v1.0.8@sha256:2e500usjuu877h7hh7......
# docker.io/kubernetesui/dashboard:v2.7.0@sha256:2e500usjuu877h7hh7......


# 3. 进入 Minikube 节点内部的 docker,测试网络连通性
# 注意:这个 docker 是 minikube 内部的,不是虚拟机宿主机上的。
minikube ssh
# 进入后,尝试直接拉取镜像(需要科学上网)
docker pull kubernetesui/metrics-scraper:v1.0.8
docker pull kubernetesui/dashboard:v2.7.0

# 可考虑从镜像加速地址下载。如:registry.cn-hangzhou.aliyuncs.com
# 1. 拉取镜像
# 2.重新 tag 为原始镜像名称和版本
# 3. 移除加速地址镜像 tag

# 退出 minikube 内部 SSH
exit

# 由于本人使用自己打的 kubernetesui/dashboard:v2.7.0 和 kubernetesui/metrics-scraper:v1.0.8 镜像。
# 因此 @sha256 值发生了变化,所以需要修改这两个镜像的拉取策略。
# 干脆直接把 image 配置改为 kubernetesui/dashboard:v2.7.0 和 kubernetesui/metrics-scraper:v1.0.8
# 去掉后面的 @sha225 值,只通过名称和版本号匹配镜像。

# 注意:如果没有修改原始镜像的 @sha256 值,则不需要编辑。
# 编辑 dashboard(vim 编辑完记得保存)
kubectl edit deployment kubernetes-dashboard -n kubernetes-dashboard
# 编辑 metrics-scraper(vim 编辑完记得保存)
kubectl edit deployment dashboard-metrics-scraper -n kubernetes-dashboard

# 4. 强制删除旧的 Pod,让系统用本地镜像重建(不行的话使用 minikube stop 和 minikube start 重启)
kubectl delete pod -n kubernetes-dashboard --all

# 再次查看状态(已经变为 Running 状态了)
kubectl get pods -n kubernetes-dashboard

# 正式启动
minikube dashboard --url

# 输出
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
http://127.0.0.1:41859/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

# 由于是在Vmware中的 Debian 启动的dashboard, 要在Windows下的浏览器中访问:
# 用SSH工具新开一个连接窗口,开启代理(aday 用户)
# kube-proxy 端口转发
kubectl proxy --address=0.0.0.0 --disable-filter=true
# 输出
W0406 00:50:07.757716   31140 proxy.go:177] Request filter disabled, your proxy is vulnerable to XSRF attacks, please be cautious
Starting to serve on [::]:8001

# 不能关闭当前SSH进程和窗口,Windows 浏览器访问 dashboard:
http://<Debian虚拟机的IP>:<端口为上面proxy中显示的端口,默认8001>/api/v1/namespaces/<服务的namespace>/services/http:<服务名称>:<服务端口>/proxy/

# Windows 浏览器访问示例:
http://192.168.233.132:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

kubectl proxy

kubectl proxy

让外部网络访问 K8S service 的 ClusterIP

bash
# 使用kubectl proxy命令就可以使API server监听在本地的8001端口上:
kubectl proxy
Starting to serve on 127.0.0.1:8001

# 如果想通过其它主机访问就需要指定监听的地址:
kubectl proxy --address=0.0.0.0

# 此时通过curl访问会出现未认证的提示:
curl -X GET -L http://k8s-master:8009/
<h3>Unauthorized</h3>

# 设置API server接收所有主机的请求:
kubectl proxy --address='0.0.0.0' --accept-hosts='^*$'
Starting to serve on [::]:8001

# 访问正常:
curl -X GET -L http://k8s-master:8009/
{
  "paths": [
    "/api",
    "/api/v1",
    ...
  ]
}

# 指定一个端口:
kubectl proxy --address='0.0.0.0' --accept-hosts='^*$' --port=8009
Starting to serve on [::]:8009

# 关于未认证的问题,干脆禁用:
kubectl proxy --address='0.0.0.0' --disable-filter=true

启用 Ingress

官方文档:https://kubernetes.io/zh/docs/tasks/access-application-cluster/ingress-minikube/

bash
# 用时较长,耐心等待,如果第一遍开启失败,多尝试几遍
minikube addons enable ingress

# 查看
minikube addons list

# 检查验证 NGINX Ingress 控制器处于运行状态
kubectl get pods -n kube-system

部署 nginx.yaml

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.16.1
          # IfNotPresent, Always, Never
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  # #如果使用Ingress, 这里可以不通过NodePort暴露端口,即可以注释掉。这里为了测试Service, 所以暴露出来
  type: NodePort
  selector:
    app: nginx
  ports:
    # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
    - port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  annotations:
    # 指定了我们使用后端ingress controller的类别,如果后端有多个ingress controller的时候很重要
    kubernetes.io/ingress.class: 'nginx'
    # nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - host: mengweijin.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80

说明

查看当前可用的 API 版本

kubectl api-versions

关于限制 cpu 和内存,建议学习环境不要限制,限制了容易启动卡死,必须分配足够的资源才行。

minikube ssh : 进入 Docker 容器

执行部署命令:

bash
# --record 标志将所执行的命令写入资源注解 kubernetes.io/change-cause 中。 这对于以后的检查是有用的。例如,要查看针对每个 Deployment 修订版本所执行过的命令。
kubectl apply -f nginx.yaml --record

使用 Service 访问应用

bash
# 方式一 VMware 虚拟机中访问
# 显示访问 service 的 url: 然后把这个 url 放到浏览器里
minikube service nginx --url
# port 通过 kubectl get service nginx 查看
curl url:port

# 方式二 Windows 下访问
# 或者通过 kubectl port-forward 端口转发的方式访问 K8S 中的应用
kubectl port-forward service/nginx 7000:80
# Windows 下访问(或用浏览器访问 mengweijin.com)
curl http://localhost:7000

# 方式三 Windows 下访问
# kube-proxy 端口转发(在新的 ssh 窗口下运行),转发端口:8001
kubectl proxy --address=0.0.0.0 --disable-filter=true
# Windows 下访问:
http://192.168.171.131:8001/api/v1/namespaces/default/services/http:nginx:80/proxy/

使用 Ingress 访问应用

bash
kubectl get ingress

# 命令行输出
PS C:\Users\mengweijin\Documents\MobaXterm\home> kubectl get ingress
NAME    CLASS    HOSTS            ADDRESS        PORTS   AGE
nginx   <none>   mengweijin.com   192.168.49.2   80      14m

Ingress 中没有配置 host 路由

bash
# 如果 Ingress 中没有配置host路由: host: mengweijin.com,直接可以使用如下IP访问到。
curl 192.168.49.2

Ingress 中配置了 host 路由

bash
# (root用户)
vi /etc/hosts
# 在 hosts 文件的末尾添加以下内容
192.168.49.2 mengweijin.com

# 使hosts立刻生效
/etc/init.d/network restart

# 说明: 如果你在本地运行 Minikube 环境,需要使用下面命令获得外部 IP 地址。 Ingress 列表中显示的 IP 地址会是内部 IP 地址。
minikube ip

# 查看 ingress 映射详情
kubectl describe ingress nginx

# 在CentOS虚拟机中访问(或用CentOS中的浏览器访问 mengweijin.com)能看到 nginx 首页
curl mengweijin.com

Windows 浏览器访问 ingress 服务

类似于访问 dashboard, 开启 proxy 后:

bash
http://192.168.171.131:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

# 照猫画虎
http://192.168.171.131:8001/api/v1/namespaces/default/services/http:nginx:/proxy/

Manage your cluster

bash
# Pause Kubernetes without impacting deployed applications:
minikube pause

# Halt the cluster:
minikube stop

# Increase the default memory limit (requires a restart):
minikube config set memory 16384

# Browse the catalog of easily installed Kubernetes services:
minikube addons list

# Create a second cluster running an older Kubernetes release:
minikube start -p aged --kubernetes-version=v1.16.1

# Delete all of the minikube clusters:
minikube delete --all

kubectl

bash
kubectl version
kubectl get namespace
kubectl get nodes
kubectl describe node nodeName
kubectl apply -f nginx.yaml --record
kubectl get deployment
kubectl get deployments
kubectl get pods
kubectl get pods -o wide
kubectl get pods --all-namespaces
kubectl get service
kubectl get all
kubectl get all --all-namespaces
kubectl describe pod nginx
kubectl delete -f nginx.yaml
kubectl delete deployment nginx
kubectl delete service nginx
kubectl logs -f podName
kubectl exec -it podName -- /bin/bash
kubectl port-forward service/nginx 7000:8888
kubectl describe quota                        # 查看当前 namespace 下的cpu, memory, storage 的限制和使用情况
kubectl get pods/podname -o yaml
kubectl get deployment ingress-nginx-controller -n kube-system -o yaml
kubectl get deployment ingress-nginx-controller -n kube-system -o yaml > ingress-nginx-controller-deploy.yaml
--enable-ssl-passthrough

kubectl patch deployment ingress-nginx-controller --patch "$(cat ingress-nginx-patch.yaml)" -n kube-system
# 监控 ingress-nginx-controller 日志
kubectl get pods -n kube-system
kubectl -n kube-system logs -f ingress-nginx-controller-84db5fd745-xqdc4

# 在 ingress-nginx-controller pod 中可以测试请求外面的服务
kubectl exec -n kube-system <ingress pod> -- curl -v <service name>:8080

kubectl exec -it -n kube-system ingress-nginx-controller-6c8559fd4d-2r8xf -- cat /etc/nginx/nginx.conf

kubectl label namespace default istio-injection-

# 从本地复制 aaa.txt 文件到 容器 application-demo-deployment-823726322c-9ssfd9 中的 /tmp 目录下
kubectl cp -n default aaa.txt application-demo-deployment-823726322c-9ssfd9:/tmp

# 从Pod容器中copy文件至本地
kubectl cp <some-namespace>/<some-pod>:<root_dir>/<parent_dir>/temp/lalalaB ./lalalaC
kubectl cp default/cloud-786d84c554-p7jz7:app/logs/app/cloud.log cloud.log

k8s 对外暴露服务的方法

向 k8s 集群外部暴露服务的方式有三种: nodePort,LoadBalancer 和本文要介绍的 Ingress。每种方式都有各自的优缺点。

  • nodePort 方式在服务变多的情况下会导致节点要开的端口越来越多,不好管理。
  • LoadBalancer 更适合结合云提供商的 LB 来使用,但是在 LB 越来越多的情况下对成本的花费也是不可小觑。
  • Ingress 是 k8s 官方提供的用于对外暴露服务的方式,也是在生产环境用的比较多的方式,一般在云环境下是 LB + Ingress Controller 方式对外提供服务,这样就可以在一个 LB 的情况下根据域名路由到对应后端的 Service,有点类似于 Nginx 反向代理,只不过在 k8s 集群中,这个反向代理是集群外部流量的统一入口。

K8S 中同一集群服务之间的访问

k8s 的服务名 DNS 解析

Kubernetes 目前使用的 kube-dns 来实现集群内部的 service dns 记录解析。默认情况下/etc/resolv.conf 里,它的内容是统一的格式。

bash
/ # more /etc/resolv.conf
nameserver 172.19.0.10
search saas.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

search doamin 列表默认情况下,它只包含本地域名。这可以通过在 search 关键字后面列出所需的域搜索路径来添加。kubernetes 为每个容器配置默认是${namespace}.svc.cluster.local svc.cluster.local cluster.local。在一次 dns 域名查询时,将会尝试使用每个 search doamin 依次搜索少于 ndots 点(默认值为 1)的解析器查询,直到找到匹配项。对于具有多个子域的环境,建议调整选项 ndots:n,以避免 man-in-the-middle 攻击和 root-dns-servers 的不必要通信。

这个我们可以把它理解成服务名 dns 解析的层次,例如{服务名}是一级,而{服务名}.{命名空间}为二层,{服务名}.{命名空间}.svc.cluster.local 是第三层,上面的配置一共有 5 层,同时也开启了 5 层,这样做可以保证最大限度的找到你的服务,但对于解析的性能是有影响的。

同一 namespace 下的 pod 之间的访问

假如 A 服务(serviceName=aaaa) 调用 B 服务(serviceName=bbbb)中的接口:http://localhost:8080/test

那么在 A 工程中可以通过 B 服务的 serviceName 来调用 B 服务。例如在 A 服务中配置 B 服务中的接口格式为:http://bbbb:8080/test

跨 namespace 下的 pod 之间的访问

假如 A 服务(namespace=ns1, serviceName=aaaa) 调用 B 服务(namespace=ns2, serviceName=bbbb)中的接口:http://localhost:8080/test

A 服务调用 B 服务的调用方式为:http://bbbb.ns2:8080/test