K8s学习总结——【一】 搭建本地集群

K8s学习总结——【一】 搭建本地集群

1 概念总结

1.1 kubernetes(k8s)

  • kubernetes(k8s)是用于管理云平台中的多个容器化应用的工具。
  • 理解:
    • 现在的大型程序被分割为多个服务,各自运行在单独的容器里。
    • 为了提升性能和可用性,多个容器需要分散在多个物理机器上,并拥有备份。
    • 多个服务和容器需要通信
    • k8s用于自动化管理此系统。

1.2 组成

物理层面
  • Master节点
    • 物理服务器
    • kubectl:操作k8s的命令行工具。添加deployment、service等。
    • apiServer:对象的请求和调用操作通过此模块提供的接口进行。
    • kube-scheduler:资源调度
    • kube-controller-manager:维护集群状态
    • etcd分布式存储:保存集群状态
  • Worker节点
    • 物理服务器
    • kubelet:创建和管理pod;与master通讯
    • kube-proxy:负责不同pod通信。
    • 资源(Pod等)
逻辑层面
  • 主要资源对象

    • Container:容器化应用。
    • Pod:k8s创建或销毁的最小单位。一个pod包含一个或多个容器。Pod中容器共享网络、存储和计算资源。
    • Service:通过labels绑定pod,提供Cluster IP地址和服务名来访问Pod资源。好处是可以实现多个Pod负载均衡,并固定访问的url,Pod IP或Cluster IP变动时不会产生影响。
    • Deployment:管理和控制Pod的数量,确保每时每刻有用户要求数量的 Pod 在工作,某Pod出现问题就重新拉起。
  • 为了更好的提供开放、扩展、规范等能力的规范

    • CNI:容器网络接口。定义通信规范,屏蔽底层使用不同网络插件的差异。
    • CSI:容器存储接口。将任意存储系统规范地暴露给容器化应用程序。
    • CRI:容器运行时接口。定义规范,使k8s可以兼容多种容器引擎,如docker、frakti等。

2 实验操作

2.1 环境准备

  • 宿主机:Windows下通过vmware运行的Ubuntu。磁盘:30GB,内存:5.2G
  • 选择用kind搭建集群

2.2 自制服务镜像

  • go 服务
    请求ip:8080/test返回字符串"hello world"
package main

import (
        "fmt"
        "net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
        if r.Method == http.MethodGet && r.URL.Path == "/test" {
                w.WriteHeader(http.StatusOK)
                fmt.Fprintln(w, "hello world")
                return
        }
        http.NotFound(w, r)
}

func main() {
        http.HandleFunc("/test", helloWorld)

        // 监听并在 8080 端口启动服务
        fmt.Println("Server is listening on port 8080...")
        http.ListenAndServe(":8080", nil)
}

  • Dockerfile
ARG IMAGE_VERSION=v0.0.1

# 使用官方的Golang基础镜像作为父镜像
FROM golang:latest as builder

# 设置工作目录
WORKDIR /app

# 将项目文件复制到容器的工作目录中
COPY . .

ENV CGO_ENABLED=0

# 构建应用
RUN go build -o main .

# 使用一个新的轻量级基础镜像,例如Alpine
FROM alpine:latest

RUN apk update

# 安装curl和其他可能需要的依赖
RUN apk add --no-cache curl

WORKDIR /app

# 复制编译好的二进制文件到新镜像中
COPY --from=builder /app/main /app/

# 设置工作目录和提供运行时环境
WORKDIR /app
CMD ["./main"]

# 声明运行时容器提供的服务端口
EXPOSE 8080

  • 运行命令
docker build -t go-hello-world-image:v0.0.1 .

2.3 kind创建集群

  • 文件结构
├── go-hello
│   ├── app
│   ├── Dockerfile
│   ├── go.mod
│   └── main.go
├── hello-deploy.yaml
├── hello-service.yaml
├── kind-config.yaml
├── nginx-deployment.yaml
└── nginx-service.yaml
  • 集群配置文件:kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.29.0 # 指定worknode镜像
- role: worker
  image: kindest/node:v1.29.0
- role: worker
  image: kindest/node:v1.29.0
  • deployment配置文件:hello-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-hello-world-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: go-hello-world
  template:
    metadata:
      labels:
        app: go-hello-world
    spec:
      containers:
      - name: go-hello-world-container
        image: go-hello-world-image:v0.0.1 # 替换为您的镜像名称和标签
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080 # 假设服务监听在容器内部的8080端口
  • service配置文件:hello-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort # 或者 LoadBalancer 如果在模拟云环境中
  selector:
    app: go-hello-world
  ports:
  - port: 30007
    targetPort: 8080
    nodePort: 30008 # 如果是NodePort类型,设置一个可用端口
  • 搭建集群
# 创建集群
kind create cluster --name hello-cluster --config kind-config.yaml
# 加载镜像
kind load docker-image go-hello-world-image:v0.0.1 --name hello-cluster
# 创建 deployment
kubectl apply -f hello-deploy.yaml
# 创建 service
kubectl apply -f hello-service.yaml
  • Docker信息概览
yzq@ubuntu:~/Documents/k8s-proj/hello$ docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED       STATUS       PORTS                                         NAMES
a20802131005   kindest/node:v1.29.0          "/usr/local/bin/entr…"   4 hours ago   Up 4 hours                                                 hello-cluster-worker
710f6226c8ab   kindest/node:v1.29.0          "/usr/local/bin/entr…"   4 hours ago   Up 4 hours   127.0.0.1:35839->6443/tcp                     hello-cluster-control-plane
c21dc643b049   kindest/node:v1.29.0          "/usr/local/bin/entr…"   4 hours ago   Up 4 hours                                                 hello-cluster-worker2
bc232db8553e   go-hello-world-image:v0.0.1   "./main"                 4 hours ago   Up 4 hours   0.0.0.0:10086->8080/tcp, :::10086->8080/tcp   hello-local
  • nodes信息
yzq@ubuntu:~/Documents/k8s-proj/hello$ kubectl get nodes -o wide
NAME                          STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION      CONTAINER-RUNTIME
hello-cluster-control-plane   Ready    control-plane   3h41m   v1.29.0   172.18.0.2    <none>        Debian GNU/Linux 11 (bullseye)   5.15.0-91-generic   containerd://1.7.1
hello-cluster-worker          Ready    <none>          3h41m   v1.29.0   172.18.0.4    <none>        Debian GNU/Linux 11 (bullseye)   5.15.0-91-generic   containerd://1.7.1
hello-cluster-worker2         Ready    <none>          3h41m   v1.29.0   172.18.0.3    <none>        Debian GNU/Linux 11 (bullseye)   5.15.0-91-generic   containerd://1.7.1
  • pods信息
yzq@ubuntu:~/Documents/k8s-proj/hello$ kubectl get pods -o wide
NAME                                         READY   STATUS    RESTARTS   AGE     IP           NODE                    NOMINATED NODE   READINESS GATES
go-hello-world-deployment-58569cd74c-85hw5   1/1     Running   0          3h33m   10.244.1.5   hello-cluster-worker    <none>           <none>
go-hello-world-deployment-58569cd74c-bd8ht   1/1     Running   0          3h33m   10.244.2.3   hello-cluster-worker2   <none>           <none>
go-hello-world-deployment-58569cd74c-qgfm7   1/1     Running   0          3h33m   10.244.1.4   hello-cluster-worker    <none>           <none>
  • service信息
yzq@ubuntu:~/Documents/k8s-proj/hello$ kubectl get service -o wide
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE     SELECTOR
hello-service   NodePort    10.96.2.242   <none>        8080:30008/TCP   3h13m   app=go-hello-world
kubernetes      ClusterIP   10.96.0.1     <none>        443/TCP          3h42m   <none>

2.4 结果与问题

使用Kind创建了集群。自定义的服务监听 port = 8080,service监听 sport = 30007,在workNode上开放 NodePort=30008

结果
1 进入到pod内部
yzq@ubuntu:~/Documents/k8s-proj/hello$ kubectl exec -it go-hello-world-deployment-58569cd74c-85hw5 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/app # curl localhost:8080/test
hello world
/app # curl 10.244.1.4:8080/test
hello world
/app # curl 10.96.2.242:30007/test
hello world
/app # curl hello-service:30007/test
hello world
  • 可以用 localhost:port访问本pod服务
  • 可以用 pod ip:port访问对应pod的服务
  • 创建Service后,可以用 clusterIP:sport可以访问服务
  • 创建Service后,无法通过 hello-service:sport访问服务 [1]
2 进入到workNode内部
docker exec -it hello-cluster-worker sh
  • 使用 localhost:NodePort可以访问本workNode上的服务;
  • 使用 WorkNodeIp:NodePort其他WorkNodeIp:NodePort无法访问服务 [2]
问题与解决

[1] 检查kube-dns,无明显错误,重启后解决。

[2] 排查过程如下:

  • 检查 ufw防火墙:未开启防火墙

  • 检查CNI日志,workNode拥有子网段,可以分配给pod
    Node hello-cluster-control-plane has CIDR [10.244.0.0/24]
    Node hello-cluster-worker has CIDR [10.244.1.0/24]
    Node hello-cluster-worker2 has CIDR [10.244.2.0/24]

  • 检查 ping:可以ping通IP

  • 通过 curl -v 查看详细信息,发现走了代理 192.168.115.1

    # Windows的IP为192.168.115.1;在这个windows里面,我运行了一个ubuntu虚拟机,IP为192.168.115.128;
    # windows上的7890端口设置了代理服务器,用于访问资源;
    # 为了让ubuntu虚拟机同样能够访问资源,我配置ubuntu的代理服务器为192.168.115.1:7890;   
    
    curl -v 172.18.0.3:30008
    
    * Uses proxy env variable no_proxy == '172.18.0.0/16,fc00:f853:ccd:e793::/64,localhost,127.0.0.1,10.96.0.0/12,192.168.59.0/24,192.168.49.0/24,192.168.39.0/24,::1,10.96.0.0/16,10.244.0.0/16,hello-cluster-control-plane,hello-cluster-worker,hello-cluster-worker2,.svc,.svc.cluster,.svc.cluster.local'
    * Uses proxy env variable http_proxy == 'http://192.168.115.1:7890/'
    *   Trying 192.168.115.1:7890...
    * Connected to 192.168.115.1 (192.168.115.1) port 7890 (#0)
    > GET http://172.18.0.3:30008/ HTTP/1.1
    > Host: 172.18.0.3:30008
    > User-Agent: curl/7.74.0
    > Accept: */*
    > Proxy-Connection: Keep-Alive
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 502 Bad Gateway
    < Connection: keep-alive
    < Keep-Alive: timeout=4
    < Proxy-Connection: keep-alive
    < Content-Length: 0
    < 
    
  • curl --noproxy:强制使用curl不走代理,访问成功

    # curl -v --noproxy '*' 172.18.0.3:30008/test
    hello world
    
  • 检查workNode上的环境变量:确实存在no_proxy环境变量

    # env | grep no_proxy
    no_proxy=172.18.0.0/16,fc00:f853:ccd:e793::/64,localhost,127.0.0.1,10.96.0.0/12,192.168.59.0/24,192.168.49.0/24,192.168.39.0/24,::1,10.96.0.0/16,10.244.0.0/16,hello-cluster-control-plane,hello-cluster-worker,hello-cluster-worker2,.svc,.svc.cluster,.svc.cluster.local'
    
  • 使用其他工具 wget访问接口:也走了代理

    # wget -O - http://172.18.0.3:30008/test
    
  • 现在问题已经在于:在kind创建的这个workNode中,path包含了proxy和no_proxy,但no_proxy没有起作用,在curl和wget都出现这个现象。

  • 回到vmware ubuntu界面,把整个虚拟机的代理关闭。

  • 重新创建集群,使用workNode:NodePort可以访问。

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值