kind

简介

kind 是 Kubernetes in Docker 的简写,是一个使用 Docker 容器作为 Nodes,在本地创建和运行 Kubernetes 群集的工具。适用于在本机创建 Kubernetes 群集环境进行开发和测试。

官网:https://kind.sigs.k8s.io/

kind 由以下组件构成:

  • Go packages implementing cluster creation, image build, etc.
  • A command line interface (kind) built on these packages.
  • Docker image(s) written to run systemd, Kubernetes, etc.
  • kubetest integration also built on these packages (WIP)

kind 使用 kubeadm 创建和启动群集节点。

kind 架构

kind 官方架构图如下,它将 docker 容器作为 kubernetes 的 “node”,并在该 “node” 中安装 kubernetes 组件,包括一个或者多个 Control Plane 和 一个或者多个 Work nodes。这就解决了在本机运行多个 node 的问题,而不需要虚拟化 (sysin)。
在这里插入图片描述

安装 Kind (必备工具)

docker官网
yum -y install yum-utils device-mapper-persistent-datalvm2
 
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 
yum makecache fast
 
yum install docker-ce docker-ce-cli containerd.io
 
systemctl start docker
 
systemctl enable docker
 
docker run hello-world
kubectl官网

kubectl 是Kubernetes的命令行工具,可以让我们通过命令访问、操作、管理Kubernetes集群。brew安装方法如下

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

mv kubectl /usr/local/bin/kubectl
kind官网
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
# 如果安装不了 用下面的
chmod +x ./kind
mv ./kind /usr/local/bin/kind
校验安装结果
kubectl version --client
kind version

关于kind 命令

  • build 用来从 k8s source 构建一个镜像。
  • create、delete 创建、删除集群。
  • export 命令目前只有一个 logs 选项,作用是将内部所有容器的日志拷贝到宿主机的某个目录下。
  • get 查看当前有哪些集群,哪些节点,以及 kubectl 配置文件的地址
  • load 可以从宿主机向 k8s 容器内导入镜像。

安装一个集群

kind create cluster

在这里插入图片描述

export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl cluster-info

在这里插入图片描述

查看当前 Kubernetes 集群中的节点信息。

kubectl get node

在这里插入图片描述

查看当前命名空间下中的Pod(容器实例)的信息。

kubectl get namespace
kubectl get po -A
kubectl get po -n kube-system

在这里插入图片描述

使用 kind create cluster 安装,关于安装方式

在这里插入图片描述
从安装打印出的输出来看,分为4步:

  1. 查看本地上是否存在一个基础的安装镜像,默认是 kindest/node:v1.13.4,这个镜像里面包含了需要安装的所有东西,包括了 kubectl、kubeadm、kubelet 二进制文件,以及安装对应版本 k8s 所需要的镜像
  2. 准备你的 node,这里就是做一些启动容器、解压镜像之类的工作
  3. 生成对应的 kubeadm 的配置,之后通过 kubeadm 安装,安装之后还会做另外的一些操作,比如像我刚才仅安装单节点的集群,会帮你删掉 master 节点上的污点,否则对于没有容忍的 pod 无法部署。
  4. 启动完毕
查看当前集群运行组件
kubectl get po -n kube-system

默认方式启动的节点类型是 control-plane 类型,包含了所有的组件

  1. 两个coredns
  2. etcd
  3. api-server
  4. controller-manager
  5. kube-proxy
  6. sheduler
  7. 网络插件方面默认使用的是 weave
查看一下 kind 下面是基础容器内部的 /kind 目录

进入容器

docker exec -it kind-control-plane /bin/bash

cd /bin
  1. 在 bin 目录下安装了 kubelet、kubeadm、kubectl 这些二进制文件
  2. 在images 下面是镜像的 tar 包,kind 在启动基础镜像后会执行一遍 docker load 操作将这些 tar 包导入
  3. 在manifests 下面是 weave 的 cni
关于: Kubelet、kubeadm 和 kubectl

Kubelet、kubeadm 和 kubectl 是 Kubernetes 生态系统中的三个关键组件,各自具有不同的功能和职责。

  1. Kubelet: Kubelet 是运行在每个 Kubernetes 节点上的组件,负责管理和控制节点上的容器。它与容器运行时(如 Docker、containerd)交互,确保 Pod 的容器在节点上正确创建、启动、停止和删除。Kubelet 还与 Kubernetes 控制平面交互,汇报节点状态和接收分配给节点的任务。
  2. Kubeadm: Kubeadm 是 Kubernetes 官方提供的用于部署和管理 Kubernetes 集群的工具。它简化了 Kubernetes 集群的初始化过程,帮助管理员在几个节点上快速创建一个稳定的、符合最佳实践的集群。Kubeadm 处理集群的引导、证书生成、网络配置、设置控制平面组件等任务,使得集群部署变得更加容易。
  3. Kubectl: kubectl 是 Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互和管理。它是与 Kubernetes API 通信的主要方式,允许用户执行各种操作,如创建、删除和管理资源(如 Pod、Service、Deployment 等)、查看集群状态、进行日志和调试等。kubectl 是与 Kubernetes 交互的主要入口。
    综上所述,Kubelet 是在每个节点上运行的组件,负责管理和控制容器;kubeadm 是用于部署和初始化 Kubernetes 集群的工具;kubectl 是用于与 Kubernetes 集群进行交互和管理的命令行工具。它们各自扮演着不同的角色,共同构建和管理 Kubernetes 集群。
关于"Weave"

Weave是一种 Kubernetes 网络插件,它提供了一个容器网络接口(Container Networking Interface,CNI)的实现。

  • CNI 是 Kubernetes 中用于管理容器网络的标准接口,它定义了一组规范和API,用于在容器运行时环境中创建、配置和连接容器网络。CNI 插件负责实现这些规范和API,以便 Kubernetes 能够为容器提供网络功能。
  • “Weave CNI” 是基于 Weave 网络的 CNI 插件。它使用 Weave 的技术和协议来创建和管理容器网络。当您在 Kubernetes 中使用 Weave CNI 时,它将负责在各个节点上创建和配置网络接口,使得容器能够在集群中进行通信。

Weave CNI 提供了一种简单而灵活的容器网络解决方案,它能够自动创建虚拟网络,并在不同节点上的容器之间建立安全的通信通道。它还支持网络策略和服务发现等功能,使您能够对容器网络进行更精细的控制和管理。
总而言之,通过使用 Weave CNI 插件,您可以轻松地在 Kubernetes 集群中创建和管理容器网络,实现容器之间的通信和连接。

创建集群

从上诉下载的文档来看默认安装的集群只带上了一个控制节点
在这里插入图片描述
默认的群集名称为kind,使用参数–name指定创建的群集的名称,可以创建多个群集:
在 node 中可以配置的不是很多,除了 role 另外的可以更改 node 使用的镜像,不过我还是使用默认的镜像创建集群

# default
kind create cluster --image kindest/node:latest
# 1.20.0
kind create cluster --image kindest/node:v1.20.0

因为前面已经创建了kind 所以命令如下 使用默认景象,创建为kind-test2 集群

kind create cluster --name kind-2

查看当前拥有哪些集群

通过 kind get clusters 可以看到当前有两个集群
在这里插入图片描述

既然有两个集群,可以通过集群切换到指定对应集群处理。kind-集群

# 切换到群集`kind`
kubectl cluster-info --context kind-kind

# 切换到群集`kind-2`
kubectl cluster-info --context kind-kind-2

删除某个集群

 kind get clusters 
 # 指定删除某个
 kind delete cluster --name kind
 # 删除全部
 kind delete cluster --all

通过yaml 文件创建集群

  1. 首先删除所有集群
kind delete cluster --all
  1. 创建配置文件 kind-config.yaml
vim kind-config.yaml 
  1. 创建集群 两个节点 一个平面
apiVersion: kind.sigs.k8s.io/v1alpha3
kind: Cluster
nodes:
  - role: control-plane
  - role: worker
  - role: worker

kind create cluster --name multi-node --config=kind-config.yaml

端口暴露

docker ps

在这里插入图片描述
在这里我被坑了好久,127.0.0.1:38884 映射容器里里面的k8s 6443 导致后无法访问serviceApi 6443端口,因为他要本地的12.0.0.1的ip4网段,这个后面会说

127.0.0.1:38884->6443/tcp

目前可以看到只有33884这个端口可以从外部访问,用kind创建K8s时,相当在本地运行了一个容器,而K8s Cluster就运行在这个容器中。
所以,如果我想从外部访问kind K8s的话,就需要把这个容器的端口(K8s的端口)暴露出来。首先删除所有 k8s cluster

kind delete cluster --all
搭建集群 带端口映射
vim kind-single  #创建一个测试单节点集群
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    kubeadmConfigPatches:
      - |
        kind: InitConfiguration
        nodeRegistration:
          kubeletExtraArgs:
            node-labels: "ingress-ready=true"
    extraPortMappings:
      - containerPort: 80
        hostPort: 8001
        protocol: TCP

创建单节点集群脚本 主机端口 8001 映射到内部容器 80

关于于 ingress-ready=true 需要解释一下

  • role: control-plane 表示该节点将作为控制平面节点运行。
  • kubeadmConfigPatches 是一个配置补丁列表,用于向节点的 kubeadm 配置添加额外的配置项。
  • kind: InitConfiguration 表示正在修改节点的初始化配置。
  • nodeRegistration 部分用于修改节点注册的相关配置。
  • kubeletExtraArgs 是一个用于在节点的 kubelet 配置中添加额外参数的字段。在这个例子中,我们添加了一个 node-labels 参数,并将它设置为 “ingress-ready=true”。
    “ingress-ready=true” 下面扩展端口映射确保只将流量发送到已准备好的节点上
kind create cluster --name tsk8s --config /usr/local/kind-config/kind-single

在这里插入图片描述

部署nginx测试

切换到当前 kind

kubectl cluster-info --context kind-kind
docker ps

创建一个需要部署的应用 nginx.yaml

 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web-nginx
  name: web-nginx-Deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata:
      labels:
        app: web-nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-nginx
spec:
  selector:
    app: web-nginx
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080

这是一个 Kubernetes 的 YAML 配置文件示例,描述了一个 Deployment 和一个 Service 的定义。

  • apiVersion: apps/v1 和 apiVersion: v1 分别指定了所使用的 Kubernetes API 的版本。apps/v1 表示使用的是 Apps API 的 v1 版本,而 v1 表示使用的是核心 API 的 v1 版本。
  • kind: Deployment 和 kind: Service 定义了资源的类型。
  • Deployment 表示定义一个 Deployment 资源,用于管理应用程序的副本。
  • Service 表示定义一个 Service 资源,用于暴露应用程序的网络服务。
  • metadata 区域包含元数据信息,如资源的标签和名称。
  • spec 区域定义了资源的规范或配置。

对于 Deployment 部分:

  • replicas: 3 指定了要创建的副本数量为 3。
  • selector 指定了用于选择要进行部署的 Pod 的标签。
  • template 定义了要创建的 Pod 的模板,其中包含了 Pod 的标签、容器以及相关的配置信息。

在 containers 下的

  • image: nginx 指定了要使用的容器镜像
  • name: nginx 为容器命名,
  • ports 下的 - containerPort: 80 指定了容器监听的端口号为 80。
    对于 Service 部分:
  • selector 指定了要将该 Service 与哪些 Pod 进行关联,通过匹配标签 app: web-nginx。
  • type: NodePort 表示 Service 类型为 NodePort,可以通过任意节点的 IP 和指定的 NodePort 来访问该 Service。
  • ports 下的 - port: 80 指定了 Service 其他 Pod 可以通过的端口号为 80,nodePort: 30080 指定了节点上的端口号为 30080,用于外部访问 Service。

这个配置文件描述了一个使用 Nginx 镜像构建的 Deployment 和一个相关的 Service,用于管理和暴露一个名为 web-nginx 的应用程序。

执行以下命令启动应用部署3个pod单位的nginx 本次发布部署为 web-nginx-Deployment

kubectl create -f nginx.yaml

http://你的主机:30070/ . 可以看到

创建集群搭建 kubernetes-dashboard 控制台

可能你会需要kubernetes的控制台

创建 kubernetes-dashboard .yaml
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Namespace
metadata:
  name: kubernetes-dashboard

---

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kubernetes-dashboard
type: Opaque

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-csrf
  namespace: kubernetes-dashboard
type: Opaque
data:
  csrf: ""

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-key-holder
  namespace: kubernetes-dashboard
type: Opaque

---

kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-settings
  namespace: kubernetes-dashboard

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
    # Allow Dashboard to get metrics.
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
    verbs: ["get"]

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: kubernetes-dashboard
          image: kubernetesui/dashboard:v2.5.0
          imagePullPolicy: Always
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            # Uncomment the following line to manually specify Kubernetes API server Host
            # If not specified, Dashboard will attempt to auto discover the API server and connect
            # to it. Uncomment only if the default does not work.
            # - --apiserver-host=http://my-address:port
          volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
              # Create on-disk volume to store exec logs
            - mountPath: /tmp
              name: tmp-volume
          livenessProbe:
            httpGet:
              scheme: HTTPS
              path: /
              port: 8443
            initialDelaySeconds: 30
            timeoutSeconds: 30
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      volumes:
        - name: kubernetes-dashboard-certs
          secret:
            secretName: kubernetes-dashboard-certs
        - name: tmp-volume
          emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        "kubernetes.io/os": linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 8000
      targetPort: 8000
  selector:
    k8s-app: dashboard-metrics-scraper

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: dashboard-metrics-scraper
  template:
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: dashboard-metrics-scraper
          image: kubernetesui/metrics-scraper:v1.0.7
          ports:
            - containerPort: 8000
              protocol: TCP
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /
              port: 8000
            initialDelaySeconds: 30
            timeoutSeconds: 30
          volumeMounts:
            - mountPath: /tmp
              name: tmp-volume
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        "kubernetes.io/os": linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      volumes:
        - name: tmp-volume
          emptyDir: {}
配置 dashboard-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    kubeadmConfigPatches:
      - |
        kind: InitConfiguration
        nodeRegistration:
          kubeletExtraArgs:
            node-labels: "ingress-ready=true"
    extraPortMappings:
      - containerPort: 31000
        hostPort: 31000
        protocol: TCP

查看端口映射情况

docker ps

0.0.0.0:31000->31000/tcp, 127.0.0.1:35017->6443/tcp

确认 kubernetes-dashboard.yaml 映射情况

在这里插入图片描述
节点映射 31000. 设置类型为nodePort 供外部访问

在这里插入图片描述


spec:
  type: NodePort
  selector:
    app: kubernetes-dashboard
  ports:
    - port: 443
      targetPort: 8443
      nodePort:31000
      protocol: TCP
创建集群
kind create cluster  --name kind-dashboard --config=/usr/local/kind-config/cluster/dashboard-cluster-config.yaml

切换到当前容器

kubectl cluster-info --context kind-kind-dashboard

应用 Dashboard

kubectl apply -f /usr/local/kind-config/kubernetes-dashboard.yaml
如果没有设置nodePort 会报错 not be used when type is ‘ClusterIP’
The Service "kubernetes-dashboard" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'

表明在 Service 对象的定义中,当 type 字段设置为 ClusterIP 时,不允许使用 nodePort 字段。nodePort 字段是用于 NodePort 类型的 Service,而不是 ClusterIP 类型的 Service。
为了解决这个问题,您可以考虑以下两种方法之一:

  • 修改 Service 对象的 type 字段为 NodePort:
  • 如果您只需要 ClusterIP 类型的 Service,请删除 nodePort 字段:

因为是修改dashboard.yaml service 端口映射,如果没有类型默认是 类型 所以要修改一下
在这里插入图片描述

创建Secret - service-account-secret.yaml
# 在kubernetes-dashboard命名空间下创建名为 admin-user 的服务账户
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
 
---
 
# 将服务账户admin-user绑定到内置的ClusterRole集群角色cluster-admin上, 实现授权
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
 
---
 
# 对名为admin-user的服务账户手动创建Secret
apiVersion: v1
kind: Secret
metadata:
  name: admin-user-secret
  namespace: kubernetes-dashboard
  annotations:
    kubernetes.io/service-account.name: admin-user
type: kubernetes.io/service-account-token

也可以不创建但是需要,创建 ClusterRoleBinding 获得群集 admin 访问权限:都是一样的,这个后面说

应用权限并拿到token
kubectl apply -f /usr/local/kind-config/service-account-secret.yaml

通过service-account-secret.yaml配置文件,给kubernetes-dashboard命名空间下名为admin-user的服务账户手动创建了一个名为admin-user-secret的Secret。现在可以通过该Secret获取相应的Token。通过kubectl describe、kubectl get两种方式获取。

kubectl describe secret admin-user-secret -n kubernetes-dashboard

查看是否ok

kubectl get po,svc -n kubernetes-dashboard

service 上面有对应的端口映射,我们前文已经暴露了,所以31000应该打service的31000
如果不想像上面一样拿token获取,还有一种,不过前期学习不建议,操作如下

  1. 创建 ClusterRoleBinding 获得群集 admin 访问权限:
kubectl create clusterrolebinding default-admin --clusterrole cluster-admin --serviceaccount=default:default
#提示:
clusterrolebinding.rbac.authorization.k8s.io/default-admin created
  1. 创建登录 Dashboard 的 token:
token=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)
  1. 拿到token
echo $token

最后访问:https://你的主机ip:31000/。拿到对应的token去访问,如果访问为不安全的的可能是证书问题,如何解决

thisisunsafe

如果不处理证书,似乎没有什么终极解决办法,

两种方案:

一,点击“高级”,再点击“继续浏览……”,下一次再打开该网页时谷歌浏览器就不会提示不是私密连接了。

二、看到“你的连接不是私密连接”画面时,直接在键盘上敲击“thisisunsafe”12个字母,谷歌浏览器会自动刷新显示网页。

java链接kind 创建的k8s

上面的案例如果看完了,基本我的坑就走完了,你已经大致明白了如何通过kind去如何创建一个k8s了,我也是摸了好多坑肝出来了,但是在机器上面操作并不满足我们的日常需求,太麻烦了,所以能不能像k8s一样去链接service端进行操作。首先说结论,是可行的。连接方式跟我们连接k8s是一样的,你完全可以按我的demo进行操作,不过我也刚打通,里面的还不是很清楚

整体demo依赖可以建一个空项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>k8sDemo</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <name>springboot-k8s</name>
    <description>k8s 介入</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.api-client</groupId>
            <artifactId>google-api-client</artifactId>
            <version>1.32.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>


        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>

        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>12.0.1</version>
        </dependency>

        <dependency>
            <groupId>io.fabric8</groupId>
            <artifactId>kubernetes-client</artifactId>
            <version>5.10.0</version>
        </dependency>

        <dependency>

            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>

    </dependencies>

</project>
package com.k8s.demo;


import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Pod;
import io.kubernetes.client.openapi.models.V1PodList;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.util.ResourceUtils;


import java.io.FileReader;
import java.io.IOException;


@Slf4j
public class KubernetesExample {
    public static void main(String[] args) {
        try {

           // 创建ApiClient
            String kubeConfigPath = ResourceUtils.getURL("classpath:config").getPath();
            ApiClient client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
            OkHttpClient httpClient = client.getHttpClient().newBuilder()
                    .hostnameVerifier((hostname, session) -> true)  // 允许任何主机名
                    .build();
            client.setHttpClient(httpClient);

            Configuration.setDefaultApiClient(client);
            CoreV1Api api = new CoreV1Api();

            // invokes the CoreV1Api client
            V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
            System.out.println("Listing all pods: ");
            for (V1Pod item : list.getItems()) {
                System.out.println(item.getMetadata().getName());
            }

        } catch (IOException e) {
            log.error("读取kubeConfigPath异常", e);
        } catch (Exception e) {
            log.error("构建K8s-Client异常", e);
        }
    }
}

关于转换

           // 从 YAML 文件加载 ConfigMap 对象
            V1ConfigMap configMap = Yaml.loadAs( ResourceUtils.getFile("classpath:k8s/format/imageFormat.yaml"), V1ConfigMap.class);

            // 修改 ConfigMap 中的某个字段,例如修改 data 部分的内容
            configMap.getData().put("new-key", "new-Job");

            // 将修改后的 ConfigMap 对象转换为 YAML 并保存到文件中
            String modifiedYaml = Yaml.dump(configMap);

            FileWriter writer = new FileWriter(ResourceUtils.getFile("classpath:k8s/format/b.yaml"));
            writer.write(modifiedYaml);
            writer.close();

关于这个:classpath:config:在你主机上输入

vim ~/.kube/config

把这个配置文件拿下来,里面有你这个主机所有集群的配置,你也可以作为参数传入进去,这个就看你自己
在这里插入图片描述

如果你看到这个样子,已经通了。但是这个连接没有证书,后面可能需要处理一下,既然已经到这里了,其实还是要聊一下k8s
可能你在连接的时候会出现以下错误


当你连接到 Kubernetes 集群时,可能会遇到 javax.net.ssl.SSLPeerUnverifiedException 异常,而异常消息是 Hostname not verified 或者类似的错误信息。

这个错误通常是由于连接的主机名与证书中的主机名不匹配引起的。为了确保安全,SSL/TLS 连接需要验证证书中的主机名与实际连接的主机名是否匹配。上文我已经忽略了


还有可能出现,Kubernetes control plane is running at https://[::1]:对应端口 这是你用了ipv6 但是又没有指定,以为他是支持ipv4 和 ipv6的
你如果对于ipv4和ipv6不了解没关系下面我会说一下


你还可能会出现 你的主机不是 127.0.0.1,而你无法通过 kubectl 访问 kind 创建的本地 Kubernetes 集群这时候你需要指定,在创建集群的时候,来源为kind 的配置文件

kind配置文件网址 对应配置 以下为我摘要的

您可以在 iptables 和 ipvs 之间配置将使用的 kube-proxy 模式。默认情况下使用 iptables

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  kubeProxyMode: "ipvs"

在这里插入图片描述

所以你可能需要配置一下地址,为0.0.0.0 这样所有ipv4的都可以访问
在这里插入图片描述


关于IPv4和IPv6

IPv4和IPv6是互联网协议的两个版本,它们之间的主要区别在于地址的格式和长度。

IPv4使用32位地址,表示为4个十进制数,每个数的取值范围为0-255,例如:192.168.0.100。IPv4地址空间有限,随着互联网的快速发展,IPv4地址已经趋于枯竭。

IPv6使用128位地址,表示为8组16进制数,每组之间用冒号分隔,例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334。IPv6拥有更大的地址空间,可以容纳更多的设备和连接。

在容器服务中,使用IPv4或IPv6来访问容器的服务有以下区别:

IP地址格式:IPv4使用点分十进制表示法,IPv6使用冒号分隔的16进制表示法。

地址空间:IPv4地址空间有限,而IPv6地址空间更加广阔。

支持设备数量:IPv6能够支持更多的设备和连接,可以满足互联网发展的需求。

兼容性:由于IPv4和IPv6是不同的地址格式,不同的网络设备和应用程序可能对IPv6支持程度不同。一些旧的设备和应用程序可能仅支持IPv4。

在选择使用IPv4还是IPv6来访问容器服务时,需要考虑网络环境、设备支持和应用程序需求等因素。同时,还需要确保网络配置正确并与容器服务的网络配置相匹配,以确保能够成功访问容器的服务。

k8s概念

先说一下常用命令


#获取资源列表:

kubectl get pods:获取所有 Pods 列表。
kubectl get deployments:获取所有部署列表。
kubectl get services:获取所有服务列表。
kubectl get nodes:获取所有节点列表。
kubectl get namespaces:获取所有命名空间列表。

#查看资源详细信息:
kubectl describe pod <pod名称>:查看特定 Pod 的详细信息。
kubectl describe deployment <deployment名称>:查看特定部署的详细信息。
kubectl describe service <service名称>:查看特定服务的详细信息。

#创建、更新和删除资源:
kubectl create -f <文件>:根据指定的 YAML 文件创建资源。
kubectl apply -f <文件>:根据指定的 YAML 文件创建或更新资源。
kubectl delete <资源类型> <资源名称>:删除指定的资源。

#执行操作:
kubectl exec -it <pod名称> -- <命令>:在特定 Pod 中执行命令。
kubectl logs <pod名称>:查看特定 Pod 的日志。

#其他常用命令:
kubectl config view:查看当前的 kubeconfig 配置。
kubectl cluster-info:查看集群的信息。
get常用命令
#以ps输出格式列出所有Pod
kubectl get pods

#以更详细的信息(如节点名称)的ps输出格式列出所有Pod
kubectl get pods -o wide

#以ps输出格式列出指定名称的单个复制控制器
#kubectl get replicationcontroller web

#以JSON输出格式列出"apps" API组的"v1"版本中的部署
kubectl get deployments.v1.apps -o json

#以JSON输出格式列出单个Pod
kubectl get -o json pod web-pod-13je7

#以JSON输出格式列出在"pod.yaml"文件中指定的类型和名称的Pod
kubectl get -f pod.yaml -o json

#使用kustomization.yaml文件从目录中列出资源 - 示例:dir/kustomization.yaml
kubectl get -k dir/

#只返回指定Pod的阶段值
kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}

#使用自定义列来列出资源信息
kubectl get pod test-pod -o custom-columns=CONTAINER:.spec.containers[0].name,IMAGE:.spec.containers[0].image

#以ps输出格式同时列出所有复制控制器和服务
kubectl get rc,services

#通过类型和名称列出一个或多个资源
kubectl get rc/web service/frontend pods/web-pod-13je7

#列出单个Pod的"status"子资源
kubectl get pod web-pod-13je7 --subresource status
config常用命令
#显示当前上下文(context)
kubectl config current-context

#从kubeconfig中删除指定的集群。
kubectl config delete-cluster 

#:从kubeconfig中删除指定的上下文。
kubectl config delete-context

#:从kubeconfig中删除指定的用户。
kubectl config delete-user

#:显示在kubeconfig中定义的集群。
kubectl config get-clusters

#:描述一个或多个上下文。
kubectl config get-contexts

#:显示在kubeconfig中定义的用户。
kubectl config get-users

#:重命名kubeconfig文件中的上下文。
kubectl config rename-context

#:在kubeconfig文件中设置单个值。
kubectl config set

#:在kubeconfig中设置一个集群条目。
kubectl config set-cluster

#:在kubeconfig中设置一个上下文条目。
kubectl config set-context

#:在kubeconfig中设置一个用户条目。
kubectl config set-credentials

#:在kubeconfig文件中取消设置单个值。
kubectl config unset

#:在kubeconfig文件中设置当前上下文。
kubectl config use-context

#:显示合并的kubeconfig设置或指定的kubeconfig文件。
kubectl config view
apply 常用命令
#:将pod.json文件中的配置应用到一个Pod。
kubectl apply -f ./pod.json

#:从包含kustomization.yaml的目录中应用资源配置。例如:dir/kustomization.yaml。
kubectl apply -k dir/

#:将stdin中的JSON配置应用到一个Pod。
cat pod.json | kubectl apply -f -

#:应用所有以'.json'结尾的文件中的配置。
kubectl apply -f '*.json'

#:应用manifest.yaml文件中匹配标签app=nginx的配置,并删除所有不在文件中且不匹配标签app=nginx的其他资源(注意:--prune仍处于Alpha阶段)。
kubectl apply --prune -f manifest.yaml -l app=nginx

#:应用manifest.yaml文件中的配置,并删除除了文件中的ConfigMap之外的所有其他配置(--prune-allowlist指定了要保留的资源类型)。
kubectl apply --prune -f manifest.yaml --all --prune-allowlist=core/v1/ConfigMap

#:编辑资源/对象的最新last-applied-configuration注释。
kubectl edit-last-applied

#:将一个活动对象上的last-applied-configuration注释设置为与文件内容匹配。
kubectl set-last-applied

#:查看资源/对象的最新last-applied-configuration注释
kubectl view-last-applied。

关于k8s整体概念

先看一张图,从这张图往下面说
在这里插入图片描述

先说一下整体概念,Kubernetes(通常简称为K8s)是一个开源的容器编排平台,用于自动化容器化应用程序的部署、扩展和管理。它允许用户对容器化应用程序进行弹性地部署和管理,以及实现自动化的容器编排和调度。它是由Google开发并开源的产品

关于图中组件

Kubernetes(K8s)包含了许多不同的组件,用于管理和运行容器化应用程序。这些组件包括:

Master组件:

  • kube-apiserver:提供了Kubernetes API的接口,用于管理集群的操作。
  • etcd:用于存储集群的配置数据和状态信息。
  • kube-scheduler:负责对新创建的Pod进行调度,将它们分配给工作节点。
  • kube-controller-manager:负责运行集群中的控制器,监控集群状态并作出相应的调整。
  • Node组件:

Node组件

  • kubelet:负责在节点上运行容器,并与Master节点进行通信。
  • kube-proxy:负责为服务提供代理和负载均衡功能。
  • Container Runtime:负责运行容器,比如Docker、Containerd等。

其他组件:

  • DNS:用于集群中的服务发现和命名解析。
  • Dashboard:提供了Web界面,可视化地管理和监控集群。
  • Ingress Controller:负责管理入口流量,允许外部流量进入集群内部。
    这些组件共同工作,构成了Kubernetes集群的基本架构,使得Kubernetes能够实现容器编排、自动扩展和高可用性等功能。

那么承接上文,我们相当于使用kind 部署了一个docker容器的k8s集群,那么k8s集群又是使用docker在k8s集群里面部署一个个pod


关于部署的整体整体流程简单说一下
  1. 用户定义应用程序的资源配置,比如Pod、Service等,然后将这些配置文件提交给Kubernetes集群的 API(kube-apiserver) 服务器。

  2. Kubernetes API服务器接收到配置文件后,将配置信息存储到etcd中,这是集群的分布式键值存储,用于存储集群的配置数据和状态信息。

  3. kube-scheduler组件负责对新创建的Pod进行调度,根据资源需求和可用性等因素,将这些Pod分配给合适的工作节点。

  4. 分配到node节点 kubelet组件在工作节点上接收到调度的Pod信息后,负责在节点上创建和管理这些Pod,并与Master节点进行通信,上报节点的状态信息。

  5. Container Runtime负责在节点上运行容器,比如Docker、Containerd等,它负责拉取镜像、创建容器等操作。

  6. kube-proxy组件负责为服务提供代理和负载均衡功能,使得集群内的服务可以被其他Pod访问。

  7. Kubernetes集群中的其他组件,比如DNS、Dashboard、Ingress Controller等,都在相应的领域提供服务,比如服务发现、监控和管理等。

整体大致流程如上

那我们在部署一个文件的时候,涉及到不通的yaml文件我们怎么区分呢,我们可以通过yaml字段里面kind类型字段来区分是什么样的资源对象类型。

  • Pod:用于定义应用程序容器的运行方式,以及与之相关的存储、网络等资源。

  • Service:用于定义服务,可以将一组Pod打包成一个服务,提供统一的访问入口。

  • Deployment:用于定义应用程序的部署方式,包括副本数量、更新策略等。

  • ReplicaSet:用于确保指定数量的Pod副本在集群中运行。

  • StatefulSet:用于部署有状态的应用程序,如数据库服务。

  • Job:用于批处理任务的定义,可以是一次性任务或定期任务。

  • ConfigMap:用于存储应用程序的配置数据。

  • Secret:用于存储敏感的安全信息,如密码、API密钥等。

  • PersistentVolume:用于定义持久化存储的卷。

  • Namespace:用于定义和隔离集群中的资源。

这是大致我熟悉的,可能还有不足需要补充


关于分布式存储nfs

其实承接上文,我们在使用kind的时候,其实我们是在一台机器上面部署了多个node节点,这会导致一个问题,我们不是多台机器,可以放在不同主机上面进行部署,所以对应我们pod挂载方面,我们需要一个分布式的存储方式,其实有很多存储方式
下面是我罗列的一些分布式存储方式,可能有不足,不过够用了,除了nfs这种存储分布式文件系统还存在。

  • GlusterFS:一个开源的分布式文件系统,可用于存储容器化应用程序的数据,并在Kubernetes中作为持久化卷使用。

  • Ceph:一个分布式存储系统,支持对象存储、文件系统和块存储,可以通过Rook项目在Kubernetes中进行部署和管理。

  • Amazon EBS(Elastic Block Store):AWS的块存储服务,可以通过Kubernetes的Volume插件在亚马逊云中进行使用。

  • Azure Disk:Azure云平台的块存储服务,可用于Kubernetes中的持久化存储。

  • Google Persistent Disk:谷歌云平台的块存储服务,也可用于Kubernetes中的持久化存储。

  • Portworx:一个软件定义的存储解决方案,可以在Kubernetes中提供容器本地存储、共享存储、备份和恢复等功能。

  • OpenEBS(Open Enterprise-Ready Storage):一个开源的企业级存储平台,支持在Kubernetes中提供容器存储和数据管理。

我这边调研使用的是nfs,用于当前机器kind集群使用存储,其他机器暴露出来,由当前机器挂载,这个在说完我们可以试着用一下

在知道这些分布式存储后我们还要对存储再来一张图,方便理解一下,在k8s中的资源分配

在这里插入图片描述

首先说pod是一个最小的容器脚本,那么他需要对应的存储空间,他需要有一个pvc文件,比如需要申请2gi的内存,同步到pv里面,需要创建一个pv,到pv里面拿到对应的空间,如果你的分布式存储是在nfs上那就简单了,就可以直接扩展到nfs分布式存储的机器上。

说起来有点抽象,举个例子就方便了参考下图

nfs分布式存储
使用nfs挂载
  1. 安装nfc必要组件
rpm -q rpcbind nfs-utils     #查询是否安装

A ,B 机器均已经安装

  1. 如果没有安装
yum install -y nfs-utils rpcbind   #安装nfs和rpc的软件包
  1. 设置共享目录
  • NFS 的配置文件为 /etc/exports ,文件内容默认为空
  • 在exports 文件中设置共享资源时,
  • 记录格式为 目录位置 客户机地址(权限选项
  • 将文件夹 /opt/web 共享给 B机器/24网段使用,允许读写操作,配置如下
# 创建共享目录
mkdir /opt/web
# 配置
vim /etc/exports
# 设置暴露目录
/opt/web B机器ip.0/24(rw,sync,no_root_squash,no_subtree_check)
# 重新加载
exportfs -ra
# 查看共享
exportfs -v
  1. 示例
# 示例格式:  <共享目录> <允许访问的主机>(参数1,参数2,...)
/opt/web  b主机ip/24(rw,all_squash)
/opt/web  b主机ip/24(rw,sync,no_root_squash)

● -r 表示重新加载所有已经配置的共享目录。
● -a 表示重新加载所有已经在 /etc/exports 文件中定义的共享目录。
● -v 参数表示“显示详细信息

关于配置文件
  1. 主配置文件:/etc/exports,文件不一定存在
  2. /usr/sbin/exportfs : 该文件是维护NFS共享目录资源的命令文件,可以使用命令重新共享/etc/exports的目录资源、卸载共享目录
  3. 日志目录:/var/lib/nfs
  4. 权限设置文件 : /var/lib/nfs/etab
关于权限
  1. 访问权限相关的参数:
    ○ rw:允许读写访问。
    ○ ro:只允许只读访问。
  2. 数据同步相关的参数:
    ○ sync:数据同步写入,对性能有一定影响,但更可靠。
    ○ async:数据异步写入,对性能更好,但不太可靠。
  3. 用户权限相关的参数:
    ○ no_root_squash:允许root用户以及具有root权限的用户拥有所有权。
    ○ root_squash:将root用户的权限限制为匿名用户权限。
    ○ all_squash:将所有用户的权限限制为匿名用户权限。
    ○ anonuid:指定匿名用户的UID。
    ○ anongid:指定匿名用户的GID。
  4. 安全相关的参数:
    ○ insecure:允许使用非特权端口(1024以下的端口)连接NFS服务器。
    ○ secure:要求使用特权端口连接NFS服务器。
  5. 子目录访问权限相关的参数:
    ○ no_subtree_check:不对子目录进行访问权限检查。

准备到这里就可以了,现在我们用A机器作为nfs的服务器,B服务器我们部署了Kind 对应的集群

服务端
mkdir /opt/web
echo "nfs test" > /opt/web/index.html
配置暴露共享目录
 vim /etc/exports
/opt/web B机器ip/24(rw,sync,no_root_squash,no_subtree_check)
配置启动
systemctl start nfs      #开启nfs服务
systemctl start rpcbind   #开启rpcbind服务
systemctl enable nfs     #开机自启nfs服务
systemctl enable rpcbind   #开机自启rpcbind服务

# 加载配置 这里的-r选项表示重新加载/etc/exports文件,而-a选项表示应用到所有共享。
exportfs -ra
客户端方面

showmount -e命令用于显示指定主机上共享的文件系统列表。在这个命令中,A是一个IP地址或主机名,可以查看共享文件系统的主机。
当命令行中运行showmount -e A时,它会返回指定主机上共享的文件系统列表。

showmount -e A机器ip
挂载 将远程主机上的/opt/web目录挂载到本地的/opt/web/目录。
mount.nfs <remote-host> : <remote-directory> <local-directory>
mount.nfs A机器ip:/opt/web /opt/web/
查看是否挂载
 df -Th

能够读取到对应的index 文件,我前面写进去的

解除挂载
umount /opt/web/

在上诉没有问题后,我们可以使用B机器使用这个A的分布式存储资源了
在这里插入图片描述
我们再理解一下这张图

开始应用到kind
创建命名空间
kubectl create namespace dev1
kubectl get namespace

关于创建的pvc pv

关于创建的pvc pv. 运行如下
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv1
  namespace: dev1
  labels:
    pv: nfs-pv1
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /opt/web #刚才我们创建的共享文件
    server: A机器ip
    readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc1
  namespace: dev1
  labels:
    pv: nfs-pvc1
spec:
  resources:
    requests:
      storage: 5Gi
  accessModes:
    - ReadWriteOnce
  selector:
    matchLabels:
      pv: nfs-pv1
---
apiVersion: v1
kind: Pod
metadata:
  name: webapp
  namespace: dev1
  labels:
    app: webapp
spec:
  containers:
    - name: webapp
      image: nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
          hostPort: 8081
      volumeMounts:
        - name: workdir
          mountPath: /usr/share/nginx/html
  volumes:
    - name: workdir
      persistentVolumeClaim:
        claimName: nfs-pvc1
EOF
查看当前pvc
kubectl get pvc -n dev1
kubectl get pods -n dev1
kubectl describe pod webapp -n dev1

在这里插入图片描述
从挂载上面来看挂载成功

进入容器查看
kubectl exec -it webapp -n dev1 -- /bin/sh

进去 /usr/share/nginx/html

cd  /usr/share/nginx/html

在这里插入图片描述
看起来成功了,但是我们又出现一个问题 每个pod创建都需要一个pvc 还有pv 太麻烦了,我们又解决办法,是有的,我们理解一下这个图

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐