kubernetesの設定を忘れないように記事にする

業務で、kubernetesを触る機会があり、せっかく触ったし忘れたくないので、やったことを備忘録として記事にまとめます。

今回kubernetesにデプロイするのはrailsアプリで、使用するコンテナのイメージにはdockerを使用します。

kubernetesのMasterNodeなどの環境は全て用意した状態で始めます。(その辺の設定を知りたい方はこの記事では紹介しませんので、すみませんが他を当たってください…)

基本概念

kubernetesの基本の概念として、マニフェストと呼ばれるyamlファイルを作成し、それを適用(apply)することで設定をkubernetesに反映させることができます。今回説明するのは、アプリを作っていく上でどういうyamlファイルが必要で、どのような役割があるのか。これをメインで説明していこうと思います。

railsアプリをkubernetesにデプロイする

namespaceを設定する(ns.yaml)

まず、namespaceを作成します。ns.yamlはnamespaceを管理するyamlファイルになります。namespaceをつけておくことで、リソースをグルーピングすることができ、作成したpodやserviceを後々確認する際に非常に役に立ちます。特に、kubernetes上に複数のアプリを管理する場合はないと不便に感じると思います。

apiVersion: v1
kind: Namespace
metadata:
  name: kube

ここで、kindをNamespaceとすることで、「namespaceを設定するyamlファイル」と定義することができます。kindにはリソース(kubernetes上の役割)を指定することができます。これからやっていきますが、podやらserviceはここで指定します。

ここで指定したmetadata.nameがネームスペース名になります。これを各リソースのyamlファイルに記載することでnamespaceを紐づけることができます。

環境変数を設定する

kubernetes内で、使用できる環境変数を作成していきます。secret.yamlを使っても設定はできますが、今回yamlファイルを作成しない方法で進めていきます。

下記コマンドを、kubernetes内で実行します。

kubectl create secret generic backend \
--from-literal=POSTGRES_USER= \
--from-literal=POSTGRES_PASSWORD= \
-n kube

-n kubeでは、namespaceを設定しており、kubeというnamespaceでbackend環境変数を管理しますよ。というコマンドになります。

こちらを、railsのアプリの環境変数として設定しておくことで、kubernetes内でpostgresSQLに接続できるようになります。

railsアプリのリソースを作成する(deploy.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: kube
  labels:
    app: backend
spec:
  replicas: 1
  revisionHistoryLimit: 0
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - image: test.jp/kube/backend:test
          imagePullPolicy: Always
          envFrom:
          - secretRef:
              name: backend
          name: backend
      imagePullSecrets:
        - name: registry
      restartPolicy: Always

こちらdeploy.yamlファイルの中身になります。

・apiVersion, kind

ここには、作成したいリソースを記載します。kindには今回deploymentリソースを作成したいのでdeployment,apiVersionはdeploymentに沿ったもの(今回はapps/v1)を作成します。

・metadata

ここにはリソースのメタデータを作成します。先ほど作成したnamespaceはここで定義します。

このデプロイメントは、「kube namespaceに所属するbackendという名前のdeployment」ということになります(この定義をすることのメリットは後ほど説明します)。

ここでlabels:appには、今後関連付けをする際のアプリ名を記載します。任意ですが、他と被らないようにしておきましょう。

・spec

ここには、作成するdeploymentの核となる部分を作成します。ここで指定しているimageはdockerで作成したイメージをk8sコンテナにpushしたものを使用しています。事前にコンテナレジストリにログインして、ローカルで作成したdockerイメージをk8sにpushしておきましょう。

envForm、-secretRefではbackendが定義されていますが、これは先ほど作成した環境変数のbackendが適用されています。

kubectl apply -f <deploy.yamlのパス>

上記コマンドを実行することで、podを作成することができます。

clusterIPの設定(service.yaml)

続いてclusterIPの設定を行います。clusterIPとはkubernetes内でIPアドレスを設定するために使用されます。外部公開する場合は、service.yamlで設定したIPアドレスとドメインを紐づけることで外部からも接続できるようになります。

apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: kube
  labels:
    app: backend
spec:
  clusterIP: "10.111.82.68"
  ports:
    - port: 3001
      targetPort: 3001
  selector:
    app: backend #backendのdeploy.yamlのメタデータで設定したものを使用。
status:
  loadBalancer: {}

上記のようにservice.yamlを作成して、下記コマンドでapplyします。

kubectl apply -f <service.yamlまでのパス>

そうすることで、railsアプリは、設定したIPアドレス、ポートで接続できるようになっています。接続確認はcurlコマンドで確認できます。

curl -I http://10.111.82.68:3001

200レスポンスが返って来れば正常に設定できています。

dbをkubernetesにデプロイする

データベースは今回、永続データを使用するために、PersistentVolume(PV),PersistentVolumeClaim(PVC)を使用します。

PVとは、ストレージを抽象化したもの(ストレージそのものではないがk8s上でストレージ定義されるもの)です。僕もここはうまく理解できていませんがPVが認証キーのようなものを握っており、Volumeにアクセスできるものと認識しています。

PVCとは、PVを呼び出すもの(ここもあまりしっかり理解できていません)という認識です。

あまり理解できていませんが、dbのdeploymentを削除しても、PVが残っていればVolumeへの接続手段は削除されずに残っており、新たにdeploymentを作成したときにPVをdeploymentの中に忍ばせれば、再度ストレージを使用することができ、永続化されるという認識です。(使用していって理解が深まれば追記していきます。)

ストレージリソース(sc.yaml)を作成する

これに関しては、うまく理解できていないので説明は割愛で…

PVを動的にプロビジョニングするためのリソースとのことです

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: kube-sc
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
volumeBindingMode: Immediate

PersistentVolume(pv.yaml)を作成する

続いて、pv.yamlを作成します。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: kube-pv
spec:
  capacity:
    storage: 20Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  storageClassName: kube-sc
  hostPath:
    path: /kube/test/db
    type: DirectoryOrCreate

spec.storageClassNameには、先ほど設定したstorageClassのkube-scを記載します。

hostPathを指定することで、クラスタ内のワーカーノード上のローカルファイルシステムへのアクセスが可能になります。/kube/test/dbディレクトリをPVとして使用することができるようになります。

PersistentVolumeClaim(pvc.yaml)を作成する

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db
  namespace: kube
  labels:
    app: db
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: kong-sc
  resources:
    requests:
      storage: 20Gi

こちらにもspec.storageClassNameにstorageClassのkube-scを記載します。

dbのリソースを作成する(deploy.yaml)

最後にdbのリソースを作成していきます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
  namespace: kube
  labels:
    app: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - image: postgres:15.2
          name: db
          args: ["-p", "5432"]
          envFrom:
          - secretRef:
              name: db
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: db
      restartPolicy: Always
      volumes:
        - name: db
          persistentVolumeClaim:
            claimName: db

上記のように、dbのdeploymentを作成していきます。

こちらのvolumeMountsでは、/var/lib/postgresql/dataとなっています。これは外部のボリュームをマウント先を指定しており、この設定によりデータの永続性が担保されます。

また、claimNameは今回、sc.yamlのnamespaceのnameを使用している点に注意です。

各マニフェスト(yaml)ファイルを適用する。

上記設定したマニフェストファイルですが、applyする順番があります。

・sc.yaml→pv.yaml→pvc.yaml→deploy.yaml

上記の順番で適用していかないと、dbのpodがうまく反映されません。

kubectl get pod -n kube

で作成したdbのstatusがrunningとなっていればうまく適用できています!

clusterIPの設定(service.yaml)

dbにもclusterIPを設定していきます。

apiVersion: v1
kind: Service
metadata:
  name: db
  namespace: kube
  labels:
    app: db
spec:
  ports:
    - port: 5432
      targetPort: 5432
  selector:
    app: db
status:
  loadBalancer: {}

以上で、設定は終了になります!

kubernetes上でrailsアプリからdbへの接続を試みる

まずは下記コマンドから、kubernetes上のアプリのコンテナ内に接続します。

kubectl exec -it <podname> -n <namespace> sh
// podnameがわからない場合下記で取得
kubectl get pod -n <namespace>

上記のコンテナ内で、データベースが作成されればokです!

rails db:create

kubernetesにアプリをデプロイしてみた

本記事では、kubernetesでアプリをデプロイする方法を記載しました。これに関しては結構作業時間もかかったし、今後またkubernetesにデプロイする機会があればこの記事を参考に進めていこうと思います。

また、kubernetes自体が有用なスキルだと思うのでどんどんこの記事の内容をアップロードして中身を充実させていって理解を深めていきたいと思います。

コメント

タイトルとURLをコピーしました