安装k3s

可以输入以下命令安装k3s

curl -sfL https://get.k3s.io | sh -s - \
  --write-kubeconfig-mode 644 \
  --node-ip <your_ip> \
  --flannel-iface <your_network_interface_name>
  • 我现在使用的是普通用户,--write-kubeconfig-mode参数可以确保普通用户可以直接运行 kubectl 命令,而不需要每次都加 sudo

  • --node-ip:我现在是静态IP,这个参数强制 k3s 使用静态 IP

  • --flannel-iface:强制使用网卡,现在我在使用Wi-Fi

    • 换成ethernet之后需要在/etc/systemd/system/k3s.service更新一下网卡

    • 重新启动

      sudo systemctl daemon-reload
      sudo systemctl restart k3s
      

管理密钥

使用k3s最大的好处就是实现GitOps,也就是把所有的部署文件,所有的服务配置放在GitHub上,这样迁移系统的时候只需要Git就能备份,非常方便,但是我们所有的secret.yaml则不能上传到GitHub,哪怕是私有仓库。为了解决这个问题,我们可以使用Age + SOPS。

Age

Age是产生密钥的工具

  • 首先在Debian中安装Age

    sudo apt update
    sudo apt install age
    
  • 生成密钥

    age-keygen -o keys.txt
    

SOPS

有了密钥,还需要工具用密钥来加密secret.yaml,在这里使用了SOPS

  • 在Debian中安装

    curl -LO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64
    chmod +x sops-v3.9.4.linux.amd64
    sudo mv sops-v3.9.4.linux.amd64 /usr/local/bin/sops
    
  • 在项目文件中创建.sops.yaml

    creation_rules:
      - path_regex: .*/secret(\.enc)?\.yaml$
        age: "age123..."
        encrypted_regex: '^(data|stringData)$'
    

    意思是SOPS会遍历项目文件,寻找名字叫secret.yaml的文件,然后只加密文件中的data或者stringData部分的内容。SOPS 默认会自动查找 ~/.config/sops/age/keys.txt,如果不想在磁盘上留下文件,或者没有这个文件夹,每次加密时可以使用环境变量把这个密钥传递给SOPS

    export SOPS_AGE_KEY="AGE-SECRET-KEY-YOUR-PRIVATE-KEY"
    
  • 执行命令,把所有的secret.yaml加密

    find . -name "secret.yaml" -exec sh -c 'sops --encrypt "$1" > "${1%.yaml}.enc.yaml"' _ {} \;
    
  • 如果想单独加密一个文件

    export SOPS_AGE_KEY="AGE-SECRET-KEY-YOUR-PRIVATE-KEY"
    sops --encrypt secret.yaml > secret.enc.yaml
    
  • 解密

    export SOPS_AGE_KEY="AGE-SECRET-KEY-YOUR-PRIVATE-KEY"
    sops -d secret.enc.yaml > secret.yaml
    
  • 加密后所有的secret.yaml就变成了secret.enc.yaml,我们可以把这些secret.enc.yaml上传到GitHub,旧的secret.yaml就可以删除了

FluxCD

现在有了加密secret.yaml的工具,该如何应用在k3s呢,这时候就要用FluxCD了,它也自带一个SOPS,但是只用来解密,会把secret.enc.yaml文件解密后的内容保存在内存里,供k3s调用

  • 在Debian中安装,当然也可以使用Helm Charts来安装FluxCD,但是官方强烈建议使用Flux CLI,也就是Bootstrap模式

    curl -s https://fluxcd.io/install.sh | sudo bash
    
  • FluxCD默认是寻找k8s的API接口(运行在8080端口),但是现在在用k3s(运行在6443端口),所以刚开始会找不到,需要修改一个文件

    sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
    
  • 检查一下

    flux check --pre
    

    如果出现一些对号,就是成功了

  • 前往 GitHub Settings → Developer settings → Personal access tokens → Tokens (classic),生成一个新 Token(Generate new token),勾选repo权限

  • 在Debian本地运行

    export GITHUB_TOKEN=Your_GitHub_Token
    export GITHUB_USER=Your_GitHub_Username
    
    flux bootstrap github \
      --owner=$GITHUB_USER \
      --repository=k3s \
      --branch=main \
      --path=./clusters/k3s \
      --personal
    
  • 由于我是把数据库和Cloudflared这种系统级别的应用放在了infra/目录下,把其他的服务放在了apps目录下,需要在clusters/k3s下创建两个文件infra.yamlapps.yaml,分别管理这两个Stack

    # infra.yaml
    apiVersion: kustomize.toolkit.fluxcd.io/v1
    kind: Kustomization
    metadata:
      name: infra
      namespace: flux-system
    spec:
      interval: 1h
      path: "./infra"
      prune: true
      sourceRef:
        kind: GitRepository
        name: flux-system
      decryption:
        provider: sops
        secretRef:
          name: sops-age     # 这里对应你在集群里创建的 secret 名字
    
    # apps.yaml
    apiVersion: kustomize.toolkit.fluxcd.io/v1
    kind: Kustomization
    metadata:
      name: apps
      namespace: flux-system
    spec:
      interval: 10m
      path: "./apps"
      prune: true
      wait: true
      dependsOn:
        - name: infra
      sourceRef:
        kind: GitRepository
        name: flux-system
      decryption:
        provider: sops
        secretRef:
          name: sops-age
    
  • clusters/k3s/flux-system/kustomization.yaml中引用这两个文件

    # clusters/k3s/flux-system/kustomization.yaml
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
      - gotk-components.yaml
      - gotk-sync.yaml
      - ../apps.yaml
      - ../infra.yaml
    
  • 运行

    kubectl create secret generic sops-age \
      --namespace=flux-system \
      --from-file=sops.agekey=keys.txt \
      --from-file=keys.txt=keys.txt
    
  • 然后粘贴keys.txt里的AGE-SECRET-KEY,它会把敏感信息直接传递给Flux,然后按CTRL+D退出

  • 到这一步,Flux就可以自动扫描你的GitHub仓库,拉下来帮你部署了,每次做完的改动只要git push到GitHub即可,如果不想等它自动给你拉,运行下面命令可以让他立即拉取

    flux reconcile kustomization apps --with-source
    flux reconcile kustomization infra --with-source
    
  • 查看部署情况

    flux get kustomization
    

使用FluxCD自动更新镜像

  • FluxCD有类似于watchtower或者keel一样的功能,也可以自动更新镜像

  • 需要安装这两个组件

    flux bootstrap github \
      --owner=Kyxie \
      --repository=k3s \
      --branch=main \
      --path=./clusters/k3s/flux-system \
      --components-extra=image-reflector-controller,image-automation-controller \
      --personal \
      --token-auth=true
    

    会要求你输入GitHub的PAT,如果忘记了可以重新生成一个

  • 创建k3s/clusters/k3s/flux-system/images.yaml,需要给每个要更新的镜像写一个配置文件,包括从哪里更新,什么情况下需要更新,这里用statistic-for-strava和homepage举例子

    # Strava
    ---
    apiVersion: image.toolkit.fluxcd.io/v1beta2
    kind: ImageRepository
    metadata:
      name: strava-repo
      namespace: flux-system
    spec:
      image: index.docker.io/robiningelbrecht/strava-statistics
      interval: 5m
    ---
    apiVersion: image.toolkit.fluxcd.io/v1beta2
    kind: ImagePolicy
    metadata:
      name: strava-policy
      namespace: flux-system
    spec:
      imageRepositoryRef:
        name: strava-repo
      policy:
        semver:
          range: '>=4.0.0'
    ---
    
    # Homepage
    apiVersion: image.toolkit.fluxcd.io/v1beta2
    kind: ImageRepository
    metadata:
      name: homepage-repo
      namespace: flux-system
    spec:
      image: ghcr.io/gethomepage/homepage
      interval: 5m
    ---
    apiVersion: image.toolkit.fluxcd.io/v1beta2
    kind: ImagePolicy
    metadata:
      name: homepage-policy
      namespace: flux-system
    spec:
      imageRepositoryRef:
        name: homepage-repo
      policy:
        semver:
          range: '>=1.0.0 <2.0.0'
    ---
    
    # Automation
    apiVersion: image.toolkit.fluxcd.io/v1beta1
    kind: ImageUpdateAutomation
    metadata:
      name: k3s-all-images-automation
      namespace: flux-system
    spec:
      interval: 1m
      sourceRef:
        kind: GitRepository
        name: flux-system
      git:
        checkout:
          ref:
            branch: main
        commit:
          author:
            email: [email protected]
            name: fluxcdbot
          messageTemplate: 'chore: Automated update image {{range .UpdatedImages}}{{ . }}{{end}}'
        push:
          branch: main
      update:
        path: ./clusters/k3s
        strategy: Setters
    
  • 在对应的deployment.yaml中加上注释

    image: robiningelbrecht/strava-statistics:v4.3.4 # {"$imagepolicy": "flux-system:strava-policy"}
    
  • k3s/clusters/k3s/flux-system/kustomization.yaml添加文件

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
    - gotk-components.yaml
    - gotk-sync.yaml
    - ../apps.yaml
    - ../infra.yaml
    - images.yaml
    
  • 最后push到GitHub即可