コンテンツにスキップ

08. ローカルにデプロイする

K3sのインストールと設定を行う

K3sをインストールする

Quick-Start Guide | K3s

1
2
# インストール
$ curl -sfL https://get.k3s.io | sh -

プライベートレジストリへのアクセスを許可する

Minikubeではminikube start --insecure-registry="xxx.xxx.xxx.xxx:xxxx"で対応していたが、k3sではregistries.yamlに書いて対応する。

Private Registry Configuration | K3s

/etc/rancher/k3s/registries.yaml
1
2
3
4
5
6
7
mirrors:
  "xxx.xxx.xxx.xxx:xxxx":
    endpoint:
      - "http://xxx.xxx.xxx.xxx:xxxx"
  "yyy.yyy.yyy.xxx:yyyy":
    endpoint:
      - "http://yyy.yyy.yyy.xxx:yyyy"
1
$ sudo systemctl restart k3s

sudoなしでkubectlを動かす

設定を行えばkubectlをユーザー権限で動かすことができる。

1
2
3
4
$ mkdir -p ~/.kube
$ sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
$ sudo chown $USER:$USER ~/.kube/config
$ chmod 600 ~/.kube/config

~/.bashrcに以下を追加する。

~/.bashrc
1
2
# k3s
export KUBECONFIG=$HOME/.kube/config
1
$ source ~/.bashrc

流れを考える

kubectlはKubernetesクラスターを制御できる。

CI/CDパイプラインにてkubectlでKubernetesクラスターにアプリケーションをデプロイさせる。

Kubernetesにおいて、クラスターへの接続先や認証情報はkubeconfigファイルで管理される。

K3sはインストール時に/etc/rancher/k3s/k3s.yamlにkubeconfigファイルを自動生成する。

CI/CDパイプライン

/etc/rancher/k3s/k3s.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
clusters:
  - cluster:
      certificate-authority-data: # 略
      server: https://xxx.xxx.xxx.xxx:xxxx # デプロイ先KubernetesクラスターのIP
    name: default
contexts:
  - context:
      cluster: default
      user: default
    name: default
current-context: default
kind: Config
users:
  - name: default
    user:
      client-certificate-data: # 略

GiteaのSettings-Actions-SecretsKUBECONFIG_CONTENTを定義する。

KUBECONFIG_CONTENT
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
clusters:
  - cluster:
      certificate-authority-data: # 略
      server: https://xxx.xxx.xxx.xxx:xxxx (デプロイ先KubernetesクラスターのIP)
    name: default
contexts:
  - context:
      cluster: default
      user: default
    name: default
current-context: default
kind: Config
users:
  - name: default
    user:
      client-certificate-data: # 略

CI/CDパイプラインにデプロイを定義する。

.gitea/workflows/workflow.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
name: Workflow
# 略
jobs:
  # 略
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Set up kubectl
        uses: azure/setup-kubectl@v4
      - name: Configure kubeconfig
        run: |
          mkdir -p ~/.kube
          echo "${{ secrets.KUBECONFIG_CONTENT }}" > ~/.kube/config
          chmod 600 ~/.kube/config
      - name: Deploy
        run: |
          kubectl apply -f ./k8s/
          kubectl rollout restart deployment/app
          kubectl rollout status deployment/app --timeout=120s

デプロイに失敗したらkubectl get podskubectl describe pod $POD_NAMEで原因を調べる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ kubectl describe pod app
# 略
Events:
  Type     Reason     Age                     From               Message
  ----     ------     ----                    ----               -------
  Normal   Scheduled  8m13s                   default-scheduler  Successfully assigned default/app-7b54b89bf9-wfjdl to rpi5
  Normal   Pulled     7m50s                   kubelet            Successfully pulled image "192.168.11.42:8085/nextjs-todo-example:latest" in 18.683s (18.683s including waiting). Image size: 102735692 bytes.
  Warning  Unhealthy  5m58s (x4 over 6m28s)   kubelet            Liveness probe failed: Get "http://10.42.0.10:3000/api/health": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
  Warning  Unhealthy  5m51s (x5 over 6m26s)   kubelet            Readiness probe failed: Get "http://10.42.0.10:3000/api/health": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
  Warning  Unhealthy  5m42s                   kubelet            Readiness probe failed: Get "http://10.42.0.10:3000/api/health": read tcp 10.42.0.1:45706->10.42.0.10:3000: read: connection reset by peer
  Warning  Unhealthy  5m36s (x8 over 7m35s)   kubelet            Readiness probe failed: Get "http://10.42.0.10:3000/api/health": dial tcp 10.42.0.10:3000: connect: connection refused
  Normal   Pulled     5m32s                   kubelet            Successfully pulled image "192.168.11.42:8085/nextjs-todo-example:latest" in 65ms (65ms including waiting). Image size: 102735692 bytes.
  Normal   Pulled     3m17s                   kubelet            Successfully pulled image "192.168.11.42:8085/nextjs-todo-example:latest" in 66ms (66ms including waiting). Image size: 102735692 bytes.
  Warning  Unhealthy  2m33s (x17 over 7m33s)  kubelet            Liveness probe failed: Get "http://10.42.0.10:3000/api/health": dial tcp 10.42.0.10:3000: connect: connection refused
  Normal   Killing    88s (x3 over 5m58s)     kubelet            Container app failed liveness probe, will be restarted
  Normal   Pulling    57s (x4 over 8m8s)      kubelet            Pulling image "192.168.11.42:8085/nextjs-todo-example:latest"
  Normal   Created    56s (x4 over 7m49s)     kubelet            Created container: app
  Normal   Pulled     56s                     kubelet            Successfully pulled image "192.168.11.42:8085/nextjs-todo-example:latest" in 63ms (63ms including waiting). Image size: 102735692 bytes.
  Normal   Started    54s (x4 over 7m46s)     kubelet            Started container app

ヘルスチェックのエンドポイントでcontext deadline exceededが出ており、アプリが起動しているが応答が遅すぎてタイムアウトしているらしい。