跳到主要内容

K8S无脑上手

前置:这里使用的是Rancher2搭建的K8S集群来上手。

创建项目、namespace、初步部署nginx、nodeport

进入集群后,导航里有一个project/namespace,项目/命名空间的点开来。

image-20221111235418401

  • namespace:是对一组资源和对象的抽象集合,用来将系统内部的对象划分为不同的项目组或用户组;常用来隔离不同的用户,比如K8S自带的服务一般运行在kube-system namespace

然后我们点击创建项目,输入项目名称,其他都不选也不填,直接点击创建。

image-20221111235813759

然后点击添加命名空间

image-20221111235921518

就填个名称,然后属于myproject项目,直接创建。

image-20221112000032683

创建完成之后点进去

image-20221112000059524

我们创建的项目就会在workloads里创建。


workload

image-20221112000158200

Pod是所有业务类型的基础,也是K8S管理的最小单位级,可以理解为它是一个或多个容器的组合。

然后我们在workloads里部署一个nginx

image-20221112001137847

这里的Node Scheduling要选择下面的,自动生成。

然后点击Add Port,输入名称,和容器内的端口,nginx内置的就是80端口,规则选择TCP,选择NodePort,最后一个会自动生成一个端口,在30000~32767范围内,在所有节点上开放一个特定的端口,任何发送到该端口的流量都被转发到对应服务。最后点击Launch,也是需要等一会的。

image-20221112001434322

这里它自动帮我们生成了一个随机的端口30370/tcp而且地址是访问的内网地址。

image-20221112001609973

可以看到主节点和另外一个节点都能进行访问。

image-20221112001648394

点进去会发现,这个是部署在k8s-node1节点上的,k8s-master1节点上没有,但是此时2个都能进行访问。

使用第二台机器的内网地址进行访问,也是可以访问的。

部署一个go api 到K8S集群中

简单一个gin代码

package main

import (
"github.com/gin-gonic/gin"
"log"
)

func main() {
r := gin.Default()
r.Handle("GET", "/", func(c *gin.Context) {
c.String(200, "this is myweb")
})
r.Handle("GET", "/user", func(c *gin.Context) {
c.String(200, "this is user 0.7")
})
err := r.Run(":80")
if err != nil {
log.Fatalln(err)
}
}

使用交叉编译成linux amd64可以使用的二进制文件

CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build myserver.go

这次还是继续选择在Rancher中选择Deploy部署一个mygo的服务,不过这次使用HostPort,它是直接将容器的端口与所调度的节点上的端口进行映射。

image-20221113221312459

如果你是别的什么云,可以选择主机端口为8081或者别的,我这个云有点特殊,和web相关的端口需要端口备案,所以选择了一个9502端口。


然后你可以将语言换成中文,来进行选择

image-20221113221544464

选择数据卷:选择映射主机目录,卷名称随意,主机路径就和你即将编译后的那个myweb的路径有关,容器目录为/app

然后这里主机调度,选择指定主机,这里只想在主机上进行运行。

image-20221113221715655

然后拉到最下面,点击显示高级选项:

image-20221113221936731

  • 命令填上./myserver,这是启动go编译好的一个二进制文件运行的命令。

  • 然后设置工作目录为我们设置好的容器映射的目录/app

  • 控制台选择无

  • 安全/主机设置:镜像拉取策略,这里因为我们使用的是alpine:3.12,我们本来不存在这个镜像,所以我们换成不存在则拉取,别的都不用动,最后点击启动。照样是要我们等一会,这个会很快的。

最终效果:

image-20221113230437734


如果是单机部署

docker pull alpine:3.12
docker run  -d  --name tt \
-v /home/wxvirus/myweb:/app \
-w /app \
-p 8081:80 \
alpine:3.12 \
./myserver

2个go api 进行负载均衡(ingress)

我们将上面部署的一个mygo进行编辑,选择部署2个节点,将pod编写成2,把前面设置的端口映射的配置删掉,重新使用NodePort来进行部署,修改主机调度为每个pod自动匹配主机,最后保存即可。


提示

中间过程偶有问题,【重启 + 删除部署 + 重新部署】是真的可以,然后再自己查看对应的日志内容,去解决即可。

我遇到的坑

首次修改保存之后,会产生大量的FailPod,你删除的速度还没他增长的快。迫不得已,把这个workloads删了,重新部署;然后主节点可以了,worker节点又不行了,原因是worker节点上那个主机映射目录的可执行文件不存在,又整了一下,然后又发现可执行文件没有执行权限,最终chmod +x myserver,等待下一次Pod重启之后才OK。

image-20221113232921379


Ingress

它相当于一个7层负载均衡器,理解为进行反向代理并定义规则的一个api对象,ingress Controller通过监听Ingress api转化为各自的配置(常用的有nginx + ingresstrafik-ingress)

image-20221113233618260

然后出去选择负载均衡,添加规则,输入名称和命名空间,然后规则里选择兹定于域名,我这里没啥域名,就不测试了,你可以选自己的域名,然后端口设置为80即可,否则访问域名则还需要加上端口才能访问,这个时候,如果你想体现出有负载均衡的感觉,你可以将myserver的代码改动一下,将输出的内容换成各个节点的名称来测试。

image-20221113234143603

ClusterIP模式、服务发现基本入门和调用

把上面的mygo再换成ClusterIP(Internal only)模式,只能内部访问,应用只要在集群内部都可以访问,外部如公网则无法访问它。类似:mysql、redis我们都不需要外部访问,就可以使用这个模式。

image-20221114223059732

image-20221114223115274

使用此模式之后,这里的IP和端口就不见了,变成这个模式之后,外部就无法访问了,我们需要自己写程序来访问。

package main

import (
"github.com/gin-gonic/gin"
"io/ioutil"
"log"
"net/http"
)

func main(){

r:=gin.Default()
r.Handle("GET","/", func(context *gin.Context) {
host:=context.Query("host")
if host==""{
context.JSON(400,gin.H{"error":"no host!"})
return
}
// http://mygo
rsp,err:=http.Get("http://"+host)
if err!=nil{
context.JSON(400,gin.H{"error":err})
}else{
b,err:=ioutil.ReadAll(rsp.Body)
if err!=nil{
context.JSON(400,gin.H{"error":err})
}else{
context.JSON(200,gin.H{"message":string(b)})
}

}
})


err:=r.Run(":80")
if err!=nil{
log.Fatal(err)
}
}

Rancher2.4使用k8s-coredns作为服务发现基础,让在同一个命名空间内的可以通过service_name直接解析。不同的则需要使用service_name.namespace_name

我们可以在同命名空间下部署一个HostPort不同端口的上面的程序交叉编译的可执行文件,分别去不同的端口去访问。

配置一台nfs服务进行跨主机文件共享

主机操作(centos7.8)

安装nfs-utils

sudo yum install -y nfs-utils

配置

sudo vi /etc/sysconfig/nfs

没有vi的可以安装一下vim

加入以下内容

LOCKD_TCPPORT=30001 #TCP锁使用端口
LOCKD_UDPPORT=30002 #UDP锁使用端口
MOUNTD_PORT=30003 #挂载使用端口
STATD_PORT=30004 #状态使用端口

启动、重启服务

sudo systemctl restart rpcbind.service
sudo systemctl restart nfs-server.service

设置开机启动

sudo  systemctl enable rpcbind.service
sudo systemctl enable nfs-server.service

编辑共享目录

sudo vim /etc/exports

写入一下内容

你所要设置的共享目录,以及对应的内网地址的网关

/home/wxvirus/goapi         内网ip公共部分.0/24(rw,async)
参数作用
ro只读
rw读写
root_squash当NFS客户端以root管理员访问时,映射为NFS服务器的匿名用户
no_root_squash当NFS客户端以root管理员访问时,映射为NFS服务器的root管理员
all_squash无论NFS客户端使用什么访问,均映射为NFS服务器的匿名用户
sync同时将数据写入到内存与硬盘中,保证不丢失数据
async优先将数据保存到内存,然后再写入硬盘;这样效率更高,但可能会丢失数据

查看挂载

showmount -e localhost
Export list for localhost:

如果不重启服务,这里是没有的

再次重启nfs服务

sudo systemctl restart nfs-server.service

再次执行查看挂载就会出现配置的内容

Export list for localhost:
/home/wxvirus/goapi 个人内网ip.0/24

到另外的主机也要安装一下nfs-utils,不需要启动nfs服务

安装完了,直接执行查看挂载的命令

showmount -e 内网ip公共部分.xx

尝试进行挂载

mount -t nfs 内网ip:/home/wxvirus/goapi /home/wxvirus/goapi

后面的文件夹你随意,这里我们写成一样的。

这个时候我们再次进入/home/wxvirus/goapi查看是否有另外一个主机创建的test.txt文件,并查看内容是否一致。

可以使用df -h来查看挂载的盘符。可以使用unmount /home/wxvirus/goapi进行卸载。

使用rancher创建PV和PVC、运行GoAPI

概念

Persistent Volume ClaimPersistent Volume

  • PV: 定义Volume的类型、挂载目录、远程存储服务器等
  • PVC:定义Pod想要使用的持久化属性,比如存储大小、读写权限等
  • StorageClassPV的模板,自动为PVC创建PV

image-20221118225412262

使用rancher创建一个持久卷

image-20221118225727446