跳转至

从k3s开始#

k3s 是轻量级单节点集群,当然也可以加入多节点。

安装#

curl -sfL https://get.k3s.io | sh -

# 中国区加速
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

运行完就安装完成了,需要保证 6443 和 443 端口可用。

卷和存储#

本地存储#

添加一个 pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc # pvc的名字,可自定义
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce # 只能被单节点读写
  storageClassName: local-path # k3s 内置的存储类,如果用 k8s 要自己添加 sc
  resources:
    requests:
      storage: 2Gi

再添加一个使用 pvc 的 deployment:mysql.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql # 选择 app: mysql 标签的 pod

  template: # 创建 pod 的模板
    metadata:
      labels:
        app: mysql # 创建 pod 时添加 app: mysql 标签,以便 Deployment 可以识别
    spec:
      containers:
        - image: mysql
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-volume # 和下面的 volumeMounts 一致才能 bind
              mountPath: /var/lib/mysql # mysql的 data 所在位置
      volumes:
        - name: mysql-volume # 和上面的 volumeMounts 一致才能bind
          persistentVolumeClaim:
            claimName: mysql-pvc # 和刚刚的pvc保持一致

分别使用 kubectl apply 添加,pvc 没有 bind 的时候是 pending 状态,成功之后变成 bound

注意 mysql.yaml 的模板中 version 是 apps/v1,这是资源路径。

如果一直显示 pending 可以使用 kubectl describe pods 查看原因,container_name需要 get pods 查看

例如这里一开始搞错了 pvc 名字,修正后 describe 得到成功。

image-20240704151857876

但此时还不能访问 mysql,因为它目前只在集群内部使用

集群服务#

集群内的 pod 需要变成 service 才能使用,有三种类型:

  • ClusterIP Service:仅限集群内
  • NodePort Service:集群外
  • LoadBalancer Service:集群外+负载均衡

NodePort#

NodePort 实际上并不推荐使用,推荐 LoadBalancer

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP # TCP|UDP
      port: 3306 # 客户端访问服务的端口
      targetPort: 3306 # 容器端口(mysql)
      nodePort: 30000 # 在每个节点都开放30000,并转发到3306,省略则不分配
  type: NodePort # ClusterIP|NodePort|LoadBalancer

注意 nodePort 要求30000-32767(可设置)

外部访问服务的路线为:外部→30000→3306(service)→3306(pod)

LoadBalancer#

一般推荐使用 loadbalancer:

apiVersion: v1
kind: Service
metadata:
  name: mysql-lb-service
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 30001
      targetPort: 3306 
  type: LoadBalancer

这时可以直接使用[集群外部IP:端口(30001)]访问。

ClusterIP#

仅限集群内访问的 ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: mysql-ci-service
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP # TCP|UDP
      port: 30002
      targetPort: 3306
  type: ClusterIP

运行后得到:

image-20240704161628962

一般来说会得到一个 CLUSTER-IP,这个 IP 不会变(自动路由到对应 pod),除非重启服务。

但推荐使用 Service Name 访问(这里是 mysql-ci-service)。这样 IP 变了也无所谓,此外 ClusterIP 还可以指定 IP。

深入:k8s 服务

本地调试#

实践中关键数据库一般不会暴露到集群外,如 mysql,假设上面我们只有一个 mysql-ci-service 可用,怎么连上mysql 进行调试呢?

  1. port-forward:使用 kubectl 端口转发:可以转发到 pod 和服务,只转发端口
  2. proxy:通过 k8s api 访问集群服务,但只能访问 http 服务
  3. 使用 telepresence:推荐

port-forward#

我们已知上面的service 名称为 mysql-ci-service,端口为 30002,则可以输入:

kubectl port-forward service/mysql-ci-service 3306:30002

就把本地端口转发到 service 的 30002,service 再转发到 pod 3306

如果要转发 pod(比如说可能想绕过 service 的负载均衡到达指定 pod),则需要得到 pod 名称,然后输入:

kubectl port-forward pod/mysql-6d57fdf866-f492r 3306:3306

proxy#

输入 kubectl proxy 即可使用

telepresence#

telepresence 可以直接拦截本地流量发送到 k8s 上,看起来就好像身处集群中。

telepresence

telepresence connect

如果想要拦截云上服务的流量,telepresence 也能做到,详细参考文档。