Kubernetes 基础介绍

发布于: 2024-05-26 · 40 min read
Kubernetes运维CICDDevOps全栈

Kubernetes 是一个开源的容器编排平台,可以轻松部署、扩展和管理容器化应用程序。这篇文章是我自学 Kubernetes 的过程,我将过程记录下来。

基础概念

弄清楚 Kubernetes 服务,要先弄清以下几个 Kubernates 的基础概念

Node

一个节点(Node)是一个虚拟机或者物理机

Pod

Pod 是 Kubernetes 最小的调度单元,一个 Pod 可以是一个或者多个容器(container)的组合,他创建了一个容器的运行环境,在这个容器中,容器可以共享一些资源,比如网络,存储以及一些运行时的配置等等。

比如我们有一个应用程序或一个数据库,我们可以将其分别放在两个不同的 pod 中。一个 Pod 运行一个容器,这是一种最佳实践。

当然,一些特殊情况,一个 Pod 也可运行多个容器,这种情况也仅限于这些容器是高度耦合的情况,即我们所说的边车模式 (Sidecar),如下图:

alt text

Service

每个 pod 都会有一个集群内部的 IP 地址,外部不可以访问到。pod 并不是一个稳定的实例,十分容易被创建或销毁,当 pod 发生故障时,会被销毁,IP 地址就会变更。这时候就需要 Kubernetes 的 Service 来管理和创建 IP 地址的变更,如下图:

service 上图的 service 连接数据库的 pod 和 App 的 pod,当 App 访问 Service 时,Service 会分配对应的数据库 IP 给 App 进行访问,如下图:

Ingress

当我们服务在本地开发时,可以用 IP 和端口号访问节点,而当部署到生产环境时,则必须配置域名,通过域名来访问

而 Ingress 就是用来管理从集群外部访问集群内部服务的入口和方式的。可以根据 Ingress 规定不同的转发规则,访问集群内部不同的 Service

除此之外,Ingress 还可以配置 SSL 证书、负载均衡等等

ConfigMap

配置完上述描述的配置后,我们就可以提供对外服务了

但还忽略一个问题,例如应用程序的 pod 访问数据库 pod 时,开发中我们会把数据库的地址、端口等连接信息写到配置文件或者环境变量中,然后在应用程序中读取这些信息。这样做,配置信息与应用程序就耦合在一起了。

一旦数据库的地址或者端口发生变化,那我们就要重新编译应用程序,再重新部署到集群中。

为了解决以上问题,Kubernetes 提供了 ConfigMap 的功能,将一些配置信息封装起来,就可以在应用程序中读取和使用了。

Secret

就是 ConfigMap的延伸,对其里面的内容进行 base64 进行编码。ConfigMap是明文的,比如我们会配置数据库访问的用户名,密码等,Secret 对这些敏感信息做编码,注意,还不是加密。base64 编码可以通过编程语言进行解析。

User, C.role, Sa

<div style="display: flex; justify-content: flex-start; align-items: center;">

</div>

这 3 个分别是身份认证、网络安全、访问控制

Volume

pod 是很容易被销毁的,数据库的 pod 一旦被销毁,其后果可能是灾难性的。K8s 提供了 Volume 组件,他可以将数据库 pod 的数据,同时同步挂载到本地的磁盘上或者集群外部的远程存储上。

这样即使 pod 被销毁,数据也能持久化存储。

Deployment

现在为止,我们还须考虑到应用程序的 pod 高可用姓,比如某个应该程序的节点发生故障,或者节点需要升级或更新维护时,应用程序就会停止服务。这显然是不能接受的。

解决方法是复制多个 Node,并用 Service 进行几种管理,此时 k8s 会自动将请求分散到其他正常工作的节点上。

而 k8s 提供了一个 Deployment 组件,用于管理所有应用程序 pod,他可以定义和管理应用程序的副本数量,以及应用程序的更新策略,简化应用程序的部署和更新操作。如下图:

deployment

Deployment 还具备

  • 副本控制 ( 就是定义应用的副本数量,如上图,定义了 3 个,如果其中一个副本有故障,那么他会自动创建一个新的副本来替代原有副本,维持副本的数量在 3 个 )
  • 滚动更新 ( 可以定义应用程序的升级策略,用于应用程序的版本升级 )
  • 自动扩容

等高级功能。

StatefulSet

相较于上面 Deployment 管理应用的副本,数据库其实也需要对应的副本管理工具,这个工具是 StatefulSet。

和应用不同的是,数据库的每个副本,都是有独立的状态的,而应用是无状态的。简单来说,10 秒前存入的数据的状态,和现在的数据的状态往往是不一样的。所以数据库的 pod,需要把数据同步到其他的副本中,或者把数据写入到一个共享的存储中。

和 Deployment 的功能类似,但 StatefulSet 还保证每个副本都有自己稳定的网络标识符和持久化存储。所以,像数据库,缓存,消息队列等等,以及一些保留了会话状态的应用,都使用 StatefulSet 来部署。

当然,一种更好的实践是将有状态的 pod 从各个节点中剥离出来,进行单独的部署

基础架构

k8s 是一个典型的 master-worker架构。所以,比如以上所提到的部署了应用和数据库的节点,也被称为工作节点 worker node。而工作节点通常有多个,master只有一个,用于管理所有 worker node

工作节点 worker node

为了能提供对外服务,每个 Node 节点上都会包含 3 个对应的服务组件,分别是:

  • kubelet,负责管理和维护每个节点上的 pod,也会定期从 api-server 组件接受新的 pod 规范,监视工作节点的运行情况,将信息汇报给 api-server。同时也负责 Volume (CVI) 和网络 (CNI) 的管理。

  • kube-proxy,负责为 pod 提供网络代理和负载均衡。

  • container runtime 容器运行时

    container runtime 就是我们常说的 Docker-Engine,每个节点都必须有容器运行时,当然,容器运行时也不止 docker,还有如:Containerd,CRI-O,Mirantis

通常情况下,一个集群包含多个节点,节点间的通信和负载均衡器就是通过 k-proxy

管理节点 master node

也称作 control panel

从上图可以看出,master 节点的结构和 worker 节点完全不同,他分别包括 API server,scheduler,control manager, etcd和 cloud control manager,通过 api server 来管理所有工作节点。

API server

就像一个集群的网关,是整个系统的入口。所有请求都会经过他,再由他分发给不同的组件进行处理。而且所有的组件间也会通过 API server 进行通信。提供认证、授权、访问控制、API 注册和发现等机制

例如,当我们部署一个新应用 pod 时,那么可以用客户端,例如 kubectl 命令行,dashboard 或者其他的 UI 界面工具。

当使用kubectl 命令行创建新的 pod 时,这个请求会先到达 api server 并验证这个请求的合法性,验证通过后再转发给相应的 Scheduler 调度器组件进行处理

Scheduler

负责监控集群中所有节点资源的使用情况,根据一些调度策略,将 pod 调度到合适的节点上运行。

例如下图:

调度器会将 pod 部署时较为空闲的节点上运行

controller manager

控制者管理器,复制管理集群中各种资源对象的状态。比如

  • 故障检测。任何一个节点上的 pod 发生故障时,必须有一种机制监测到这个故障,尽快对其进行处理。例如重启该 pod 或者新启用一个 pod 进行替换。
  • 自动扩展
  • 滚动更新

controller manager 是如何知道哪个节点发生故障的呢?这就需要下面介绍的 etcd 组件

etcd

这个是一个高可用的键值存储系统,类似 Redis,存储集群中所有资源对象的状态信息。比如哪个 pod 挂掉,哪个 pod 又被新创建了。可以理解为集群的大脑。是整个集群的数据存储中心。

cloud controller manager

云控制器管理器,他是用来和各种云上的 api 进行交互的。而且他能提供一致的管理接口,使得用户可以在不同云平台中管理他们的应用程序。

minicube 搭建单节点环境

本文为了实践 k8s,在本地搭建了个模拟线上的简易版环境来学习 k8s。

minikube 是一个轻量级的 Kubernetes 实现,可在本地计算机上创建虚拟机,并部署仅包含一个节点的简单集群。

一般生产环境的 Kubernetes 集群,一般都是使用云厂商提供的 Kubernetes 服务,如阿里云的 ACK、腾讯云的 TKE、华为云的 CCE 、AWS 的 EKS 等 。他们需要多个节点的集群才能实现高可用。每个节点都是一个服务器或者虚拟机。所以本地开发环境可以使用 minikube 来验证 Kubernetes 的功能。

安装

1# macOS
2brew install minikube
3
4# Windows
5choco install minikube
6
7# Linux
8curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
9sudo install minikube-linux-amd64 /usr/local/bin/minikube

minikube 常用命令

1# 帮助菜单
2minikube
3
4# 启动
5# 后面的参数是国内网络问题下载镜像失败时加,如果下载成功,不加也可以:
6minikube start --image-mirror-country=cn
7
8# 检查状态
9minikube status

kubectl 命令

安装完成 minikube 之后,附带 kubectl 命令,这个命令就是 Kubernetes 自带的和集群交互的命令

1(base) zyzy:~ $ kubectl get nodes
2NAME       STATUS   ROLES           AGE    VERSION
3minikube   Ready    control-plane   8m9s   v1.30.0

multipass 虚拟机 + K3s 的多节点集群搭建

minikube 是一个单节点的集群环境,但是稍微复杂一点的环境就不适用了。这里我们用虚拟机和 k3s 技术,模拟一个多节点环境的搭建。

multipass 安装

超级简单,点击这里 multipass 点击相应的版本安装即可

multipass 常用命令

  • 创建一个 ubuntu1 虚拟机
1(base) zyzy:~ $ multipass launch --name k3s --cpus 2 --memory 4G --disk 10G
2Launched: k3s
  • 查看本机所运行的所有虚拟机
1(base) zyzy:~ $ multipass ls
2Name                    State             IPv4             Image
3k3s                     Running           192.168.64.3     Ubuntu 24.04 LTS
  • 进入 k3s 虚拟机系统
1(base) zyzy:~ $ multipass shell k3s
2。。。
3ubuntu@k3s:~$
  • 启用虚拟机
1(base) zyzy:~ $ multipass start k3s
  • 停止虚拟机
1(base) zyzy:~ $ multipass stop k3s
  • 删除虚拟机
1(base) zyzy:~ $ multipass delete k3s
2# 永久删除已经delete的虚拟机
3(base) zyzy:~ $ multipass purge
4

设置 ssh 远程登录 multipass

设置密码登录

在 K3s 虚拟机上操作:

1# 登录我们上面设置的k3s虚拟机内部:
2multipass shell k3s
3# 在k3s虚拟机内部,修改sshd_config 文件:
4sudo vim /etc/ssh/sshd_config

打开并修改以下配置:

1-- # PermitRootLogin prohibit-password
2++ PermitRootLogin yes
3
4-- # PasswordAuthentication yes
5++ PasswordAuthentication yes
6
7-- # PubkeyAuthentication yes
8++ PubkeyAuthentication yes
1# 重启ssh使其生效
2sudo service ssh restart

设置 ubuntu 用户密码,并退出虚拟机尝试用密码登录:

1sudo passwd ubuntu
2exit

在 mac terminal 下查询虚拟机 ip 地址,并运行 ssh 登录虚拟机:

1multipass ls
2ssh [email protected]

设置 ssh 公私钥登录

上面的登录步骤每次都要输入密码过于繁琐,我们可以像 GitHub 一样配置公私钥则每次登录都不需要输入密码,具体步骤如下:

本地环境下生成 RSA 密钥对,我在登录 GitHub 时生成过密钥对,可以忽略这一步:

1# 生成密钥对,如已生成则略过这一步
2ssh-keygen -t rsa -b 4096

所有密钥对会放在~/.ssh/文件夹下,显示公钥并复制所有内容

1cat ~/.ssh/id_rsa.pub

重新进入 k3s 虚拟机并粘贴我们上面复制的公钥,注意,要全个文件内容都替换,完成后退出

1multipass shell k3s
2vim ~/.ssh/authorized_keys
3exit

在本地将私钥复制到 k3s 虚拟机上:

1ssh-copy-id [email protected]

此时会看到复制成功的提示:

到这一步,已经可以用 ssh 直接登录而无需每次输入密码了,而成功设置了 ssh 登录,则上面的 multipass shell k3s 登录方式则会失效

设置别名登录

上面每次都要输入 ssh [email protected] 登录比较麻烦,这里可以设置别名登录:

本地电脑上设置 alias,在 terminal 上输入:

1alias k3s="ssh [email protected]"

该命令只在当前终端有效,如果要长期生效,必须写在~/.zshrc 或 ~/.bash_profile文件的最后一行,并执行 source 生效

1source ~/.zshrc

k3s 安装

登录进虚拟机后,安装 k3s 的 master 节点:

1curl -sfL https://get.k3s.io | sh -
2
3# 国内用户使用:
4curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

kubectl命令验证是否安装成功:

1ubuntu@k3s:~$ sudo kubectl get nodes
2NAME   STATUS   ROLES                  AGE   VERSION
3k3s    Ready    control-plane,master   23s   v1.29.4+k3s1

创建 worker node

上面我们已经安装好了 master node,下面我们来安装 worker node

先在 master 节点上获取 token,并复制下来

1ubuntu@k3s:~$ sudo cat /var/lib/rancher/k3s/server/node-token

重新开一个 mac 的终端,输入

1(base) zyzy:~ $ TOKEN=$(multipass exec k3s sudo cat /var/lib/rancher/k3s/server/node-token)
2(base) zyzy:~ $ echo $TOKEN
3K10dc6a...

可以看到能 echo 打印出相应的 token,证明 token 配置成功,再将 master 的 IP 地址配置到本地并验证

1(base) zyzy:~ $ MASTER_IP=$(multipass info k3s | grep IPv4 | awk '{print $2}')
2(base) zyzy:~ $ echo $MASTER_IP
3192.168.64.3

我们可以继续创建两个 worker 节点并将其配置到 master 节点中

1multipass launch --name workder1 --cups 2 --memory 8G --disk 10G
2multipass launch --name workder2 --cups 2 --memory 8G --disk 10G
3
4# 在worker节点虚拟机上安装k3s,得用国内的镜像:
5 for f in 1 2; do
6     multipass exec worker$f -- bash -c "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=\"https://$MASTER_IP:6443\" K3S_TOKEN=\"$TOKEN\" sh -"
7 done

验证,让我们进入 k3s 的 master 节点中,可以看到 worker1 worker2节点已经加入到集群中:

1(base) zyzy:~ $ multipass shell k3s
2...
3ubuntu@k3s:~$ sudo kubectl get nodes
4NAME      STATUS   ROLES                  AGE   VERSION
5k3s       Ready    control-plane,master   55m   v1.29.4+k3s1
6worker1   Ready    <none>                 15m   v1.29.4+k3s1
7worker2   Ready    <none>                 15m   v1.29.4+k3s1

kubectl 管理工具

1# 进入k3smaster节点:
2multipass shell k3s

基础命令

1# 查看帮助文档
2kubectl --help
3
4# 查看API版本
5kubectl api-versions
6
7# 查看集群信息
8kubectl cluster-info
9

创建 kubectl create 及运行kubectl (run | apply)

1# 创建并运行一个指定的镜像
2kubectl run NAME --image=image [params...]
3# e.g. 创建并运行一个名字为nginx的Pod
4kubectl run nginx --image=nginx
5
6# 根据nginx.yaml配置文件创建资源
7kubectl create -f nginx.yaml
8# 根据URL创建资源
9kubectl create -f https://k8s.io/examples/application/deployment.yaml
10# 根据目录下的所有配置文件创建资源
11kubectl create -f ./dir
12
13# 通过文件名或标准输入配置资源
14kubectl apply -f (-k DIRECTORY | -f FILENAME | stdin)
15# e.g.
16# 根据nginx.yaml配置文件创建资源
17kubectl apply -f nginx.yaml

查看 kubectl (get | describe)

1# 其中,RESOURCE可以是以下类型:
2kubectl get pods / po         # 查看Pod
3kubectl get svc               # 查看Service
4kubectl get deploy            # 查看Deployment
5kubectl get rs                # 查看ReplicaSet
6kubectl get cm                # 查看ConfigMap
7kubectl get secret            # 查看Secret
8kubectl get ing               # 查看Ingress
9kubectl get pv                # 查看PersistentVolume
10kubectl get pvc               # 查看PersistentVolumeClaim
11kubectl get ns                # 查看Namespace
12kubectl get node              # 查看Node
13kubectl get all               # 查看所有资源
14
15# 后面还可以加上 -o wide 参数来查看更多信息
16kubectl get pods -o wide
17
18# 查看某一类型资源的详细信息
19kubectl describe RESOURCE NAME
20# e.g. 查看名字为nginx的Pod的详细信息
21kubectl describe pod nginx

调试 kubectl logs 交互 kubectl exec

比如上面用 replilcaset 创建的 pod,查看日志

1sudo kubectl logs nginx-deployment-6d6565499c-bn7gd

也可以进入 pod 内部查看:

1ubuntu@k3s:~$ sudo kubectl exec -it nginx-deployment-6d6565499c-bn7gd -- /bin/bash
2root@nginx-deployment-6d6565499c-bn7gd:/#

修改,删除和清理资源

1# 更新某个资源的标签
2kubectl label RESOURCE NAME KEY_1=VALUE_1 ... KEY_N=VALUE_N
3# e.g. 更新名字为nginx的Pod的标签
4kubectl label pod nginx
5# 删除某个资源
6kubectl delete RESOURCE NAME
7# e.g. 删除名字为nginx的Pod
8kubectl delete pod nginx
9
10# 删除某个资源的所有实例
11kubectl delete RESOURCE --all
12# e.g. 删除所有Pod
13kubectl delete pod --all
14
15# 根据YAML配置文件删除资源
16kubectl delete -f FILENAME
17# e.g. 根据nginx.yaml配置文件删除资源
18kubectl delete -f nginx.yaml
19
20# 设置某个资源的副本数
21kubectl scale --replicas=COUNT RESOURCE NAME
22# e.g. 设置名字为nginx的Deployment的副本数为3
23kubectl scale --replicas=3 deployment/nginx

例如:

1# 删除名为nginx的pod
2ubuntu@k3s:~$ sudo kubectl delete pod nginx
3pod "nginx" deleted
4
5# 删除名为 nginx-deployment 的 deployment
6ubuntu@k3s:~$ sudo kubectl delete deployment nginx-deployment
7deployment.apps "nginx-deployment" deleted
8ubuntu@k3s:~$ sudo kubectl get all
9NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
10service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   10h

Deployment

利用 kubectl 创建

以上是创建的的基本命令,但实际操作中,创建一个 pod, 更提倡使用 Deployment 这样的上层资源来创建,具体如下:

1# nginx-deployment 为别名
2kubectl create deployment nginx-deployment --image=nginx
3
4# 查看已创建的deployment
5sudo kubectl get deployment

查看已创建的 Deployment 资源:

1# 查看所有pod,包括非deployment创建的
2ubuntu@k3s:~$ sudo kubectl get pod
3NAME                                READY   STATUS    RESTARTS   AGE
4nginx                               1/1     Running   0          6h44m
5nginx-deployment-6d6565499c-bn7gd   1/1     Running   0          2m35s
6
7# 通过 deployment 查看 pod
8ubuntu@k3s:~$ sudo kubectl get deployment
9NAME               READY   UP-TO-DATE   AVAILABLE   AGE
10nginx-deployment   1/1     1            1           85s
11
12# 通过 replicaset 查看 pod
13ubuntu@k3s:~$ sudo kubectl get replicaset
14NAME                          DESIRED   CURRENT   READY   AGE
15nginx-deployment-6d6565499c   1         1         1       6m52s

修改 replicaset 副本数量:

上面的 replicaset 是通过 deployment 创建时自动生成的,实际上他是一个管理副本数量的组件

可以通过 edit 来编辑 replicaset 的 ymal 文本

1ubuntu@k3s:~$ sudo kubectl edit deployment nginx-deployment
2deployment.apps/nginx-deployment edited

当输入以上命令后,会自动进入 nginx-deployment 的 yaml 文件进行编辑,我们把replicas值改为 3 后保存退出

1ubuntu@k3s:~$ sudo kubectl get pod
2NAME                                READY   STATUS    RESTARTS   AGE
3nginx                               1/1     Running   0          7h11m
4nginx-deployment-6d6565499c-bn7gd   1/1     Running   0          29m
5nginx-deployment-6d6565499c-m26m2   1/1     Running   0          4m28s
6nginx-deployment-6d6565499c-sjvql   1/1     Running   0          4m27s
7
8ubuntu@k3s:~$ sudo kubectl get replicaset
9NAME                          DESIRED   CURRENT   READY   AGE
10nginx-deployment-6d6565499c   3         3         3       29m

查看后发现 pod 多了 3 个同属于一个 replicaset 的 pod

利用 yaml 文件创建 (重点)

kubectl 命令行方式创建 pod 可以加入很多参数,例如我们上面举例过的 --image=nginx ,这个参数如果一多或者嵌套的话,那么命令行的方式是非常麻烦的,这时,更推荐利用 yaml 文件的方式创建。

yaml类似 Docerfile,创建后再用 kubectl 进行调用,pod 就会自动更新了。

具体步骤:

  1. 创建并编辑 yaml 文件
1ubuntu@k3s:~$ vim nginx-deployment.yaml

编辑如下,下面是一个最基本的 yml 文件

1apiVersion: apps/v1
2metadata:
3  name: nginx-deployment
4spec: # 顶层 spec 定义 deployment 的配置信息
5  selector:
6    matchLabels:
7      app: nginx
8  replicas: 3 # replicas 定义副本数量
9  template:
10    metadata:
11      labels:
12        app: nginx
13    spec: # 底层 spec 定义 pod 的详细信息
14      containers:
15        - name: nginx
16          image: nginx:1.25
17          ports:
18            - containerPort: 80 #向外暴露的端口
  • apiVersion : 指定 apiServer 版本,格式是:组别/版本号,group/version,组别经常有 apps(应用), batch(批处理), autoscaling(自动扩缩容) 等等
  • kind: 用来指定资源对象的类型
  • metadata: 定义资源对象的元数据,比如资源的名称,标签,命名空间等。
  • spec: 是 specification 的缩写,定义资源的各种配置信息,包括有多少个副本 (replicas), 像上面的 spec 有两层嵌套,第一层是定义 deployment 的信息,第二层是定义 Pod 的配置信息
  1. 经 yml 文件创建创建资源 kubectl create -f
1ubuntu@k3s:~$ sudo kubectl create -f nginx-deployment.yaml
2deployment.apps/nginx-deployment created
3
4# 检验
5ubuntu@k3s:~$ sudo kubectl get all
6NAME                                   READY   STATUS    RESTARTS   AGE
7pod/nginx-deployment-cd5968d5b-h4nng   1/1     Running   0          3h42m
8pod/nginx-deployment-cd5968d5b-bg649   1/1     Running   0          3h42m
9pod/nginx-deployment-cd5968d5b-qcs7t   1/1     Running   0          3h42m
10
11NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
12service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   16h
13
14NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
15deployment.apps/nginx-deployment   3/3     3            3           3h42m
16
17NAME                                         DESIRED   CURRENT   READY   AGE
18replicaset.apps/nginx-deployment-cd5968d5b   3         3         3       3h42m
  1. 修改(kubectl apply) 删除 (kubectl delete)
1# 通过文件名或标准输入配置资源
2kubectl apply -f (-k DIRECTORY | -f FILENAME | stdin)
3# e.g.
4# 根据nginx.yaml配置文件创建资源
5kubectl apply -f nginx.yaml
6
7# 删除
8kubectl delete -f nginx-deployment.yaml

Service

利用 kubectl 创建

上面我们用 Deployment 创建了 5 个 pod,我们可以用以下命令查询到其 IP 地址:

1ubuntu@k3s:~$ sudo kubectl get pod -o wide
2NAME                               READY   STATUS    RESTARTS   AGE     IP           NODE      NOMINATED NODE   READINESS GATES
3nginx-deployment-cd5968d5b-h4nng   1/1     Running   0          4h3m    10.42.0.10   k3s       <none>           <none>
4nginx-deployment-cd5968d5b-bg649   1/1     Running   0          4h3m    10.42.3.4    worker2   <none>           <none>
5nginx-deployment-cd5968d5b-qcs7t   1/1     Running   0          4h3m    10.42.1.5    worker1   <none>           <none>
6nginx-deployment-cd5968d5b-rml8k   1/1     Running   0          2m32s   10.42.3.5    worker2   <none>           <none>
7nginx-deployment-cd5968d5b-z8k52   1/1     Running   0          2m32s   10.42.1.6    worker1   <none>           <none>

这些 pod 的 IP 地址都是节点内部地址,无法提供对外服务,所以我们必须创建 Service 并配置其外部服务

创建步骤:

1# 创建服务命令
2sudo kubectl create service nginx-service
3# 对外暴露已有 deployment
4sudo kubectl expose deployment nginx-deployment

查看已经创建服务:

1ubuntu@k3s:~$ sudo kubectl get svc
2NAME               TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
3kubernetes         ClusterIP   10.43.0.1     <none>        443/TCP   17h
4nginx-deployment   ClusterIP   10.43.54.95   <none>        80/TCP    22s

删除服务:

1sudo kubectl delete service nginx-deployment

利用 yml 文件创建(重点)

1vim nginx-service.yaml

内容如下:

1apiVersion: v1
2kind: Service
3metadata:
4  name: nginx-service
5spec:
6  type: NodePort # 指定对外暴露类型
7  selector:
8    app: nginx
9  ports:
10  - protocol: TCP
11    port: 80 # 对外端口
12    targetPort: 80 # pod内部端口
13    nodePort: 30080
  • type: 该参数指定了对外端口类型,如果不定义该字段,那么默认是 Cluster IP 类型服务,只能在节点内部间访问,NodePort为对外服务,具体类型参加下表
  • nodePort: 该参数指定了对外暴露的端口号,范围必须在 30000~32767之间
服务类型描述
ClusterIP默认类型,集群内部的服务
NodePort节点端口类型,将服务公开到集群节点上
LoadBalancer负载均衡类型,将服务公开到外部负载均衡器上
ExternalName外部名称类型,将服务映射到一个外部域名上
Headless无头类型,主要用于 DNS 解析和服务发现

启用:

1sudo kubectl apply -f nginx-service.yaml

查看 pod 的 ip 地址:

1ubuntu@k3s:~$ sudo kubectl get nodes -o wide
2NAME      STATUS   ROLES                  AGE   VERSION        INTERNAL-IP    EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
3k3s       Ready    control-plane,master   17h   v1.29.4+k3s1   192.168.64.3   <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.15-k3s1
4worker2   Ready    <none>                 17h   v1.29.4+k3s1   192.168.64.6   <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.15-k3s1
5worker1   Ready    <none>                 17h   v1.29.4+k3s1   192.168.64.5   <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.15-k3s1

复制一个任意一个 worker 节点的 ip,并在浏览器打开,发现打开成功,端口采用我们配置的 nodePort: 30080

deployment

portainer 图形界面管理工具

安装及访问

有两种方法:

  1. 获取 portainer 的 yaml 文件配置安装,安装在 master 节点

  2. 利用 helm 安装,安装在本地

    • helm 是 k8s 的包管理工具,利用以下命令安装

    • Mac 电脑:

    1brew install helm
    2helm repo add portainer https://portainer.github.io/k8s/
    3helm update portainer
    4helm upgrade --install --create-namespace -n portainer portainer portainer/portainer --set tls.force=true

删除

删除 portainer 时,由于我们加了命名空间,所以也要指定命名空间,如下:

1sudo kubectl delete namespace portainer

命名空间 kubectl get ns | namespace

上面提到的命名空间,可以用以下命令查看所有集群里的命名空间

1ubuntu@k3s:~$ sudo kubectl get ns
2NAME              STATUS   AGE
3kube-system       Active   18h
4kube-public       Active   18h
5kube-node-lease   Active   18h
6default           Active   18h
7portainer         Active   10m

上面 portainer是我们指定的命名空间,其余是 k8s 默认创建的

平时创建任何资源如果不指定命名空间,则全部默认放到 default 的命名空间里

namespace

从上图可以发现,如创建了命名空间的资源,查看时必须加上 -n 参数

访问

这里我们要输入 master 节点的 IP,而不是 portainer 的 IP,所以本地访问 master 节点的 ip+端口号 30777,本地 master ip 用sudo kubectl get pod -o wide查找,例如浏览器访问 master 节点:http://192.168.64.3:30777

可以看到访问的页面:

portainer portainer

评论区