K3s部署记录

第N次,和 K3S打上了交道。因为K8S的技术的学习曲线较为陡峭。也因为自己基础不牢。 基础部署都没熟练直攻Helm。

然后导致集群就处于失控状态,从而导致了最终的学习/研究失败。

现在重新捡起来,使用基础的例子一步步的构建K3S homelab体系。

最终的目的是可以把目前所有的 docker-compose 的项目都迁移到K3S下面来。

Workshop 说明

需求背景

因为国内的网络环境问题,拉取Docker的gcr/dockerio 之类的镜像时有失败。而且因为集群的多节点。导致 ImagePullErr 问题时有发生。

所以这里需要建立起一个 在本地提供镜像缓存以及管理功能的 Registry。

选型

官方的Registry镜像中提供了一个 remote_porxy 的配置,可以直接实现对某一个远程仓库的 代理和 缓存功能。

不过这里有一个进行二次打包的版本 yangchuansheng/registry-proxy 把一些配置直接写到了环境变量中去。简化了我们的使用流程。

在有提供 代理服务的 仓库镜像之后,还需要一个管理工具,用来对我们的镜像进行可视化的webui管理。这里找到了下面的那这个项目

可以直接进行部署用来Registry的资源管理。

实践过程

持久化存储

因为需要进行镜像的缓存,所以对于拉去的镜像需要进行持久化存储。这里原计划是使用NFS来提供存储,不过这种基础的服务不希望降低系统的整体性。所以就在Master 的节点拓展了磁盘。直接进行磁盘的localpath存储。

多个的镜像代理都是公用的一个PV存储,这样便于管理且不会冲突。下面的yaml就是对这个 PV 的定义

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: master-local-storage
spec:
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  capacity:
    storage: 15Gi
  local:
    path: /data
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: node-role.kubernetes.io/storage
              operator: In
              values:
                - storage
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-path
  volumeMode: Filesystem

这里需要注意的是两点,其中一个是 persistentVolumeReclaimPolicy

Reclaim Policy

Current reclaim policies are:

  • Retain — manual reclamation
  • Recycle — basic scrub (rm -rf /thevolume/*)
  • Delete — associated storage asset such as AWS EBS or GCE PD volume is deleted

Currently, only NFS and HostPath support recycling. AWS EBS and GCE PD volumes support deletion.

img

另一个是 nodeAffinity,通过下面的scheme 来进行。

小技巧使用 kubectl explain svc –recursive 来进行API的递归列出

或者使用 api reference 来进行查询 Kubernetes API/Config and Storage Resources/PersistentVolume

rms@k3s-master:~$ kubectl explain PersistentVolume.spec.nodeAffinity --recursive
KIND:       PersistentVolume
VERSION:    v1

FIELD: nodeAffinity <VolumeNodeAffinity>

DESCRIPTION:
    nodeAffinity defines constraints that limit what nodes this volume can be
    accessed from. This field influences the scheduling of pods that use this
    volume.
    VolumeNodeAffinity defines constraints that limit what nodes this volume can
    be accessed from.

FIELDS:
  required  <NodeSelector>
    nodeSelectorTerms   <[]NodeSelectorTerm> -required-
      matchExpressions  <[]NodeSelectorRequirement>
        key <string> -required-
        operator    <string> -required-
        values  <[]string>
      matchFields   <[]NodeSelectorRequirement>
        key <string> -required-
        operator    <string> -required-
        values  <[]string>

PVC 对PV 来进行 Claim,以提供给POD 来进行使用。

apiVersion: v1
kind: Namespace
metadata:
  name: container-basis

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: container-basis
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  volumeMode: Filesystem
  volumeName: master-local-storage
  resources:
    requests:
      storage: 10Gi

多个站点的Proxy Deploy部署&UI 部署

这里简单的就是一个 Deployment 的部署方式,这里的yaml 定义了Proxy 的Deploy ,配置都是比较浅显易懂的。 这个是根据官方进行进行二次打包的镜像。其中的一些配置值可以直接通过环境变量来直接传入。

其中需要注意的是,Resources.limits 是推荐进行设置的否则存在容器对资源的过度使用的问题。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-gcr-registry
  namespace: container-basis
  labels:
    app: k8s-gcr-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8s-gcr-registry
  template:
    metadata:
      labels:
        app: k8s-gcr-registry
    spec:
      containers:
      - name: k8s-gcr-registry
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            memory: "512Mi"
            cpu: "500m"
        image: yangchuansheng/registry-proxy:latest
        ports:
        - containerPort: 5000
          protocol: TCP
        volumeMounts:
        - name: local
          mountPath: /hub
        env:
        - name: REGISTRY_HTTP_ADDR
          value: :5000
        - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
          value: /hub
        - name: PROXY_REMOTE_URL
          value: https://k8s.gcr.io
      volumes:
      - name: local
        persistentVolumeClaim:
          claimName: registry-pvc

关于多个缓存站点的定义,其yaml文件的大多数都是相同的。其具体的差异在Env 的部分。比如下面这个就是代理Gcr 的配置 。

  env:
  - name: REGISTRY_HTTP_ADDR
    value: :5000
  - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
    value: /hub
  - name: PROXY_REMOTE_URL
    value: https://gcr.io

Service 以及 Ingress

在Registry运行之后,就需要考虑到前面的接入部份,定义servic和对应的ingress 来作为七层的路由转发。从而实现对集群外提供访问。具体的配置文件如下。

service的几个类型,不指定默认是 ClusterIP 的模式。

---
apiVersion: v1
kind: Service
metadata:
  name: k8s-gcr-registry-svc
  namespace: container-basis
  labels:
    run: k8s-gcr-registry
spec:
  selector:
    app: k8s-gcr-registry
  ports:
    - protocol: TCP
      port: 5000

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry-ingress-k8s-gcr
  namespace: container-basis
  annotations:
    kubernetes.io/ingress.class: "traefik"
spec:
  rules:
  - host: k8s-gcr-k3s.io
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service: 
            name: k8s-gcr-registry-svc
            port:
              number: 5000

代理接入配置

在前面的部分已经完成了Registry 的基础部署,后面就是使用上的配置。这里直接使用 ansible来进行配置文件的部署。

先写Host到所有的节点中,用来劫持几个镜像域名的指向到我们自建的registry的IP。

然后重启节点服务来进行应用生效

For K3s

- hosts: k3s
  remote_user: ep
  become: yes
  gather_facts: False
  vars_prompt:
  - name: "registryIP"
    prompt: "Please input Registry Server IP"
    private: no
  tasks:
    - name: add hosts
      when: registryIP is defined
      shell: |
        sudo sed -i '/^.*hub-k3s\.io.*/d' /etc/hosts
        sudo echo "{{ registryIP }}  hub-k3s.io      gcr-k3s.io        k8s-gcr-k3s.io" >> /etc/hosts
    - name: add remote private registry
      when: registryIP is defined
      shell: |
        ls -als /etc/rancher/k3s/registries.yaml > /dev/null 2>&1 || sudo mkdir /etc/rancher/k3s/
        sudo echo > /etc/rancher/k3s/registries.yaml
        sudo cat <<EOT >> /etc/rancher/k3s/registries.yaml
        mirrors:
          docker.io:
            endpoint:
              - "http://hub-k3s.io"
          gcr.io:
            endpoint:
              - "http://gcr-k3s.io"
          k8s.gcr.io:
            endpoint:
              - "http://k8s-gcr-k3s.io"
        EOT

- hosts: k3s-master
  remote_user: ep
  become: yes
  tasks:
    - name: restart server
      shell: sudo systemctl restart k3s

- hosts: k3s-workers
  remote_user: ep
  become: yes
  tasks:
    - name: restart workers
      shell: sudo systemctl restart k3s-agent

For Docker

普通的Docker服务直接修改 /etc/docker/daemon.json 加上下面的配置。因为Docker 默认的修改的只有 Dockerio 的地址。

"registry-mirrors": ["http://hub-k3s.io"],
"insecure-registries" : ["http://hub-k3s.io"]

对于其他的镜像仓库的域名。需要使用自定义的域名来代替代理前的域名。

image-20231112184322318

一步步的来,在体系树上一片片叶子的补全

发表回复

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