k8s 入门指南

本文主要是记录我个人近期学习k8s群集的内容

由于是站在初学者的角度来编写的,难免会存在许多的问题

如果你发现了错误或者需要改进的地方,也欢迎你指出

前情提要

由于我是使用别人部署好的群集进行实战,所以本文不会有教你如何部署群集的过程

并且只是从受限制的管理员权限的角度进行操作,还请注意和作为群集所有者进行操作群集的区别

获取kubectl和oidc插件

安装kubectl

官方文档:https://kubernetes.io/zh-cn/docs/tasks/tools/

windows来这边:https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-windows/

不过你会发现它让你用curl,Chocolatey、Scoop 或 winget 安装,其实不用管它也行

把二进制文件下过来就好了(curl那步的命令里有文件地址)

https://dl.k8s.io/release/v1.30.0/bin/windows/amd64/kubectl.exe

编写本文时的地址如上

安装OIDC插件

https://github.com/int128/kubelogin

直接去release里下载

windows在本文编写时最新的地址为https://github.com/int128/kubelogin/releases/download/v1.28.1/kubelogin_windows_amd64.zip

注意

kubectl的版本号最多只能和群集差异一个小版本号,不管更新还是更旧,否则会无法通讯

配置kube和登录群集

配置kube config

通常路径~/.kube/config

windows下为"C:\Users\用户名\.kube\config"

config是一个纯文本的yaml文件且无后缀名,具体内容你应该向群集管理员取得

如果需要指定namespace,那么请参考以下位置

contexts:
  - context:
      cluster: cluster-name
      user: your-username-oidc
      namespace: 在这里填写命名空间
    name: 群集名称

配置环境变量

随便找个地方,放置你取得的两个exe

然后将解压得到的kubelogin插件,重命名为kubectl-oidc_login.exe

写入环境变量PATH

接下来执行kubectl get pod

你应该会看到弹出认证界面在浏览器中,完成验证即可继续操作,此时已经完成了登录

概念

Pod

Pod是我们通常情况下操作和管理群集的最小单位

容器运行在pod中,一个pod中可能有多个相同服务的容器在运行,用于均衡负载和容灾

PV、PVC

全称为PersistentVolume、PersistentVolumeClaim,也就是永久卷永久卷声明

可以简单的理解为永久存储卷,和docker那边的持久化存储是类似的玩意

在全程手动分配的情况下可能会出现先定义pv,在定义pvc的情况

实际上大多数情况下我们只需要直接编写pvc即可,告诉主控(我想要个卷),然后让群集自己分配一个出来,不用在乎pv是如何被定义的

Service(svc)、Ingress

用于暴露服务给外面,否则容器只能在容器间相互通讯

具体差异看下文

常用命令:获取容器状态

获取pod

kubectl get pod

返回

NAME READY STATUS RESTARTS AGE
python-pod 1/1 Running 0 3h17m

获取Service(svc)

kubectl get svc 

返回

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
python-service ClusterIP 10.1.2.120 <none> 30000/TCP 3h19m

此处举例的是没有外部ip的情况

获取节点(Node)

你可以使用以下命令获取集群中所有节点的 IP 地址:

kubectl get nodes -o wide

返回

NAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
node1 Ready master 12d v1.18.8 192.168.1.10 <none> Ubuntu 20.04.1 LTS 5.4.0-42-generic docker://19.3.12
node2 Ready <none> 12d v1.18.8 192.168.1.11 <none> Ubuntu 20.04.1 LTS 5.4.0-42-generic docker://19.3.12

注意,受限的管理员账户可能无法执行此命令

常用命令:通过YAML创建/删除容器

此部分内容可参考docker-compose up -d和docker-compose down

创建(应用配置)

kubectl apply -f 配置文件

删除(停止容器)

kubectl delete -f 配置文件

需要注意的是,k8s没有实际意义上提供停止和重启容器的命令,需要实现类似效果你只能通过创建和删除容器

pvc、pod、service等服务的创建和删除通常也使用yaml直接进行,这样便于维护

常用命令:进入pod容器内部操作

注意,前提是这个pod在正常运行

并且和docker一样,一旦入口进程结束工作,那么整个容器都会停止运行

然后群集可能尝试重启它,注意不要搞出无限重启,然后退出的死循环,否则会非常糟糕

kubectl exec -it pod名称 -n 命名空间 -- /bin/bash

当然,也可能会遇到容器镜像里连个bash都不剩的情况,那么可以试试sh之类的

kubectl exec -it pod名称 -n 命名空间 -- /bin/sh

常用命令:从本地向群集复制文件

通常在首次部署pod时会用到它,将文件传入到pv中

kubectl cp 本地路径 命名空间/pod名称:pod内的绝对路径

注意,执行的前提也是有一个正常工作的pod且已被挂载了对应的pv,不能不经过pod直接把文件丢进pv里

常用命令:删除指定服务

-n 参数用于指定命名空间,通常来说它是可选的

删除 PersistentVolumeClaim(PVC)

kubectl delete pvc pvc名称 -n 命名空间

删除 Pod

kubectl delete pod pod名称 -n 命名空间

删除 Service

kubectl delete svc service名称 -n 命名空间

删除 Ingress

kubectl delete ingress ingress名称 -n 命名空间

将端口暴露给外部

TL;DR

  • NodePort 适合简单的开发和测试环境,或者需要快速验证服务的场景。(对于测试环境,也可以通过Lens将端口映射回到本地)
  • LoadBalancer 适合在云环境中部署的生产级服务,尤其是需要自动负载均衡和固定外部 IP 地址的场景。
  • Ingress 适合复杂的 HTTP/HTTPS 服务和多域名场景,提供细粒度的流量控制和更高的安全性。

在 Kubernetes 中,NodePort、LoadBalancer 和 Ingress 是三种将集群内部服务暴露给外部访问的方式。它们之间的主要区别如下:

NodePort

工作原理

  • NodePort 服务在每个节点的某个固定端口(通常是 30000-32767 范围内的端口)上开放服务。
  • 该端口将流量转发到集群内的相应服务。
  • 用户可以通过 NodeIP:NodePort 访问服务。

优点

  • 简单易用,配置相对简单。
  • 不需要额外的负载均衡器。

缺点

  • 需要手动指定或查询 NodePort 端口号。
  • 每个节点都需要开放相应的端口,安全性和管理性较差。
  • 不适合大规模的生产环境,因为无法自动进行负载均衡。

LoadBalancer

工作原理

  • LoadBalancer 服务会创建一个外部负载均衡器(例如 AWS ELB、GCP LB),并将流量转发到集群内的服务。
  • 负载均衡器会自动分配一个外部 IP 地址,用户可以通过该 IP 地址访问服务。

优点

  • 自动进行负载均衡,适合大规模生产环境。
  • 外部用户可以通过固定的 IP 地址访问服务。

缺点

  • 依赖云服务提供商提供的负载均衡器,因此需要支付额外费用。
  • 配置和管理相对复杂。

Ingress

工作原理

  • Ingress 是一种 API 对象,管理集群内的 HTTP 和 HTTPS 路由。
  • 它通过定义路由规则,将外部流量转发到集群内的服务。
  • 需要一个 Ingress Controller 来实现具体的负载均衡和路由功能(例如 Nginx Ingress Controller)。

优点

  • 可以根据域名、路径等进行细粒度的流量控制和路由。
  • 支持 TLS/SSL 终结,提供更高的安全性。
  • 适合复杂的 HTTP/HTTPS 服务和多域名场景。

缺点

  • 需要部署和配置 Ingress Controller,初始配置相对复杂。
  • 主要用于 HTTP/HTTPS 流量,对于其他协议支持有限。

补充:CLUSTER-IP是什么?

CLUSTER-IP 是 Kubernetes 中 Service 的内部 IP 地址,用于在集群内不同 Pod 之间通信。CLUSTER-IP 是一个虚拟 IP 地址,分配给每个 Service,确保集群内的 Pod 可以通过该 IP 地址访问相应的服务,而不需要直接知道服务背后的具体 Pod IP 地址。

具体用途

  1. 集群内部通信CLUSTER-IP 主要用于集群内部的服务发现和通信。集群内的其他 Pod 可以通过该 IP 地址访问服务,而无需了解具体的 Pod IP 地址。
  2. 负载均衡:Kubernetes Service 会将流量均匀分配到后端的多个 Pod 上,实现负载均衡。

Ingress类似平时使用的CDN回源的情况,依靠host名称来区分服务和流量指向,因此也只能用于穿透web服务

如果需要穿透标准TCP服务,那么你需要使用NodePortLoadBalancer,当然他们也需要外部具有ipv4/v6公网地址才行,否则用了也是白用

Ingress在配置合理的情况下,不需要节点具有外部公网地址也可以使用(家里云也行)

注意

这三者只能由群集所有者进行配置,作为操作者你只能使用他们来暴露服务

例如Ingress,在外部回源回到群集服务中时,目标地址也需要群集所有者来告诉你

实战:创建一个使用Python官方镜像的pod来运行负载

注意,请自行修改name和namespace以符合你的需求

先起一个PV用于存放程序

# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: python-pvc
  namespace: moeworld
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

此处的storage: 1Gi代表这是个1G空间的pv,需要多少空间自己改数字即可

启动Pod并暴露服务

# python-pod-service.yaml
apiVersion: v1
kind: Pod
metadata:
  name: python-pod
  namespace: moeworld
  labels:
    app: python-app
spec:
  containers:
  - name: python-container
    image: python:3.11
    ports:
    - containerPort: 35640
    volumeMounts:
    - mountPath: /data
      name: python-data
    command: ["/bin/bash", "-c", "tail -f /dev/null"]
  volumes:
  - name: python-data
    persistentVolumeClaim:
      claimName: python-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: python-service
  namespace: moeworld
spec:
  selector:
    app: python-app
  ports:
  - protocol: TCP
    port: 35640
    targetPort: 35640
  type: ClusterIP

这份配置文件我们使用了一个没有实际负载的入口命令用于保活(以便于我们把文件先复制进pv)

并使用ClusterIP将端口暴露了出去

command: ["/bin/bash", "-c", "tail -f /dev/null"]

这里就是容器启动后,自动执行的命令,我们需要在把程序放入pv后,然后删除pod,修改command并把真正的启动命令写到这里,重启pod

至此,这个容器应该已经能够正常工作了

如果需要使用Ingress来回源

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: python-ingress
  namespace: moeworld
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  rules:
  - host: 你的域名(不要带http/https)
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: python-service
            port:
              number: 35640

port: number: 35640 这里即为指定的端口号

遇到过的问题

The Service "***" is invalid: * spec.ports[0].name: Required value * spec.ports[1].name: Required value

在 Kubernetes 中,Service 的端口配置需要包含名称。名称字段是必需的

它在内部用于区分多个端口配置。我们需要为每个端口配置添加一个名称

Pod反复重启,但是就是启动不了

可能是由于pod配置文件里缺少了入口命令command,当入口进程结束,中控会认为这个容器已经挂了,会尝试重启(但是没有入口命令就永远都不可能收到入口进程在运行的信号)

点赞

赞助商广告

如果您的网络和设备条件允许,这里可能会显示来自Google的广告

发表回复

电子邮件地址不会被公开。必填项已用 * 标注