Time4VPSにk3dでhello-appを本番デプロイするまで


k3dとは?

Rancherが公開しているk3sという軽量版Kubernetesを
dockerを使ってクラスタ構築してくれる代物です。
VPSにdocker-composeで本番運用してしまっているなんていう人には
代替手段となり得るツールかと思います。

全体の流れ

はじめに

今回は、テストということで出来る限り無料に近い構成で
k3dを使ってクラスタを構築していきます。
サーバーは海外の最強激安VPS Time4VPSを採用し、
ドメインは無料ドメイン取得ができる
freenomで取得していきます。
dockerコンテナイメージはこいつを使っていきます。

Time4VPSサーバーを用意

まずはこちらからvpsサーバーを用意しましょう。
ちなみに当記事で利用するOSの種類はUbuntu18.04です。
vpsの契約が完了したら下記の記事あたりを参考にガリガリとUbuntuの初期設定をしていきます。
Ubuntu 最低限抑えておきたい初期設定

Time4VPSにk3dをインストール

k3dにはもちろんdockerが必要なので、まずはdockerをインストールします。
Ubuntuにdockerをインストールする場合はこちらの記事を参考にするのがオススメです。
Ubuntu 18.04にDockerをインストールする(+docker-composeも)

dockerがインストールできたらk3dをインストールします。

curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash

k3dでクラスタを構築する

それではいよいよk3dでクラスタを立てます。
<your vps global ip>の箇所は自分の用意したvpsのipを適用してください。

k3d cluster create hoge-cluster --agents 2 --api-port <your vps global ip>:6550 -p 80:80@agent[0] -p 443:443@agent[0]

ローカルのkubectlと繋ぐ

まずサーバー側で下記を実行しcertificate-authority-dataとユーザーのpasswordをひかえておく

vi ~/.kube/config

ローカルの~/.kube/configに今回作成したclusterの情報、context、userを追加する
これで、ローカルのkubectlとTime4VPS上のクラスタが繋がる

~/.kube/config(ローカル)
apiVersion: v1
kind: Config
current-context: hoge-cluster
preferences: {}

clusters:
  - name: hoge-cluster
    cluster:
      certificate-authority-data: <your certificate-authority-data in vps ~/.kube/config>
      server: https://<your vps global ip>:6550

users:
  - name: admin@hoge-cluster
    user:
      password: <your password in vps ~/.kube/config>
      username: admin

contexts:
  - name: hoge-cluster
    context:
      cluster: hoge-cluster
      user: admin@hoge-cluster

クラスタに接続できたか確認

kubectl get node

NAME                        STATUS   ROLES    AGE   VERSION
k3d-hoge-cluster-agent-0    Ready    <none>   39m   v1.18.8+k3s1
k3d-hoge-cluster-agent-1    Ready    <none>   39m   v1.18.8+k3s1
k3d-hoge-cluster-server-0   Ready    master   39m   v1.18.8+k3s1

クラスタにcert-managerをインストールする

続いてサービスをSSLで配信するためクラスタにcert-managerをインストールします。
cert-managerはマニフェスト一発でインストール完了するので導入自体は超簡単です。
cert-managerのインストール

freenomで無料ドメインを取得する

テストで試しに動かしてみる程度でわざわざ有料のドメインを取得するなど勿体ないと思います。
なのでfreenomという無料ドメイン取得に便利な
サービスを利用します。
取得するドメイン名は今回はk3d-hello-app.tkとでもしておきます。

マニフェストファイルを書いてデプロイ

最後にマニフェストファイルを書いてデプロイします。
今回、コンテナイメージはgoogleがGKE用のサンプルとして公開しているレジストリを利用するため
イメージのビルド作業もリモートレジストリへのpush作業もないので寂しい作業になりますが
k8sというマニフェストを管理するディレクトリを用意し
2種類のマニフェストファイルを用意していきましょう。

# ディレクトリ構成はこんな感じ
.
└── k8s
    ├── hello-app.yaml
    └── ingress.yaml
k8s/hello-app.yaml

apiVersion: v1
kind: Service
metadata:
  name: hello-app-service
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    app: hello-app

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app-deployment
spec:
  replicas: 6
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
        env: stage
    spec:
      containers:
        - image: gcr.io/google-samples/hello-app:1.0
          name: hello-app
          ports:
            - containerPort: 8080

ちなみにServiceのタイプがLoadBalancerになっていますが
k3dはtype: LoadBalancerを使うことができます。

続いて、ingress用のマニフェストファイルを書きます。
<your mail address>の箇所にはご自身のメールアドレスを置き換えてください。

k8s/ingress.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-issuer
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration, update to your own.
    email: <your mail address>
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-issuer
    solvers:
      - http01:
          ingress:
            class: traefik
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: letsencrypt-cert
spec:
  dnsNames:
    - k3d-hello-app.tk

  secretName: letsencrypt-cert-tls
  issuerRef:
    name: letsencrypt-issuer


---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hoge-cluster-ingress
  annotations:
    ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: "traefik"
    certmanager.k8s.io/issuer: "letsencrypt-issuer"
    certmanager.k8s.io/acme-challenge-type: http01
spec:
  tls:
    - secretName: letsencrypt-cert-tls
      hosts:
        - k3d-hello-app.tk

  rules:
    - host: k3d-hello-app.tk
      http:
        paths:
          - path: /
            backend:
              serviceName: hello-app-service
              servicePort: 8080

それではマニフェストを適用します。

kubectl apply -f k8s -R

ちなみに-Rフラグは今回必要ないのですが
もしも、マニフェストファイルの内容が膨大になった。とかになったら
マニフェストファイルをパッケージ分割する必要も出てくるかと思います。
そういった時に-Rフラグをつけるとパッケージ分割したマニフェストも
再起的に適用してくれると、そういう事です。


# 例えばこんな感じにパッケージ分割
.
└── k8s
    ├── hello-app.yaml
    └── ingress
        ├── certificate.yaml
        ├── ingress.yaml
        └── issuer.yaml

マニフェストが適用できたらブラウザで確認してみましょう。
下記のように表示されSSL化もできていれば完了です!

まとめ

k3dは一つの物理サーバーの中に仮想でNodeを立て
クラスタを構築するので、物理サーバー層での可用性は全くありません。
1台のサーバーが一時停止すればドカン!と丸ごと
そのクラスタで運用しているサービスは一時停止します。
いわゆる、Blast Radiusはデカイどころの騒ぎじゃありません。
もはや一撃必殺ですww
なのでビジネス規模によっては全く要件に合わないでしょうが
個人規模などランニングコストの節約の方を重視する場合などは
k3dのような仮想クラスタというものもありなのではないでしょうか?
特にこれまで個人でdocker-composeで本番運用してました!
というような方には超オススメです。

参考