PRIVATE CLOUD OPENSHIFT – P3: Sử dụng OKD kết hợp với NFS server

Bài viết này là một phần của chùm bài viết: Private cloud OpenShift Bạn có thể đọc phần trước: “PRIVATE CLOUD OPENSHIFT – P2: Nâng cấp“ Ở bài viết P1, NFS server có tên là okd4-nfs và có ip là 192.168.99.53 NFS server này dùng để chứa Registry và các Data cần được mount vào

Bài viết này là một phần của chùm bài viết: Private cloud OpenShift

Bạn có thể đọc phần trước: “PRIVATE CLOUD OPENSHIFT – P2: Nâng cấp

Ở bài viết P1, NFS server có tên là okd4-nfs và có ip là 192.168.99.53
NFS server này dùng để chứa Registry và các Data cần được mount vào các container như là database chẳng hạn.

I/ Cài đặt okd4-nfs:

1. Tiền xử lý:

Cài hệ điều hành CentOS-8.3.2011-x86_64, với ip là 192.168.99.53 và để DNS: 192.168.99.51
Cài dịch vụ để đồng bộ ngày giờ: chrony
Cài NFS server: nfs-utils

2. Cấu hình NFS server:

-Firewalld

$ firewall-cmd --permanent --add-service=nfs
$ firewall-cmd --permanent --add-service=rpc-bind
$ firewall-cmd --permanent --add-service=mountd
$ firewall-cmd --reload

-Thiết lập thư mục để share:

$ mkdir /data
$ mkdir /data/registry
$ mkdir /data/opt
$ mkdir /data /database
$ chmod 777 /data/registry
$ chown nobody:nobody /data/registry

(Thư mục /data được thiết lập để chứa dữ liệu lớn, mount ổ đĩa 2Tb vào chẳng hạn)
-Thiết lập /etc/export:

/data 192.168.99.0/24(rw,sync,no_root_squash,no_all_squash,no_wdelay)

-Refresh và Verify lại NFS khi vừa thay đổi cấu hình

$ exportfs -r
$ exportfs -v

II/ Các vấn đề cần xử lý khi vừa cài xong OKD:

1. image-registry operator:

-Đứng tại okd4-services, tạo file /tmp/registry_pv.yaml với nội dung sau:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: registry-pv
spec:
  capacity:
    storage: 300Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/registry
    server: 192.168.99.53

-Tạo Persistent Volume cho Registry:

$ oc create -f /tmp/registry_pv.yaml
$ oc get pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM  STORAGECLASS   REASON   AGE
registry-pv   300Gi      RWX            Retain           Avaiable                                10s

-Sửa image-registry operator:

$ oc edit configs.imageregistry.operator.openshift.io
sửa: managementState: Removed -> managementState: Managed
sửa: storage: {} -> storage:
                      pvc:
                        claim:
$ oc get pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                             STORAGECLASS   REASON   AGE
registry-pv   300Gi      RWX            Retain           Bound    openshift-image-registry/image-registry-storage                           2m

-Expose service image-registry

$ oc patch svc image-registry -p '{"spec":{"externalIPs":["192.168.99.64","192.168.99.65"]}}' -n openshift-image-registry
$ oc get svc -n openshift-image-registry
NAME                              TYPE          CLUSTER-IP        EXTERNAL-IP                     PORT(S)      AGE
image-registry                    ClusterIP     172.30.120.99     192.168.100.64,192.168.100.65   5000/TCP     3d
image-registry-operator           ClusterIP     None              <none>                          60000/TCP    3d

2. HTPasswd Setup:

-Tạo thêm các user đăng nhập vào OKD

$ cd /tmp
$ htpasswd -c -B -b users.htpasswd k.admin abcxyz
$ htpasswd -B -b users.htpasswd kevin.chu abcxyz

(ví dụ tạo thêm 2 user: admin và kevin.chu có password là abcxyz)
-Apply vào OKD:

$ oc create secret generic htpass-secret --from-file=htpasswd=users.htpasswd -n openshift-config
$ oc apply -f htpasswd_provider.yaml
>oauth.config.openshift.io/cluster configured

-Gán quyền cluster-admin đến user k.admin:

$ oc adm policy add-cluster-role-to-user cluster-admin k.admin
>clusterrole.rbac.authorization.k8s.io/cluster-admin added: "k.admin"

Sau khi tạo xong, mỗi lần đăng nhập OKD sẽ thấy như hình sau:

Click vào htpasswd_provider và đăng nhập vào OKD với user k.admin vừa tạo ở trên.

III/ Chạy thử 1 app

App được chọn làm ví dụ là database Postgres 15.1
App sẽ được quản lý dưới project test

-Tạo nơi lưu trữ dữ liệu database postgres:
Đứng ở server nfs

$ mkdir /data/test-testdb
$ chown 999:999 /data/test-testdb

Những bước còn lại thao tác trên server okd-services

-Tạo project “test” từ user k.admin đã được tạo ở trên
Đây là 1 điểm khác biệt của OpenShift với Kubernetes: OpenShift dùng khái niệm project, còn Kubernetes dùng khái niệm namespace. Tuy nhiên 2 cái là một

Khi login vào OKD từ command line “oc login”, nó cần có certificate-authority (mặc dù đã dùng tham số insecure-skip-tls-verify=true)
Tạo file certificate-authority giả:

$ touch /tmp/a.crt

Login vào OKD và tạo project test

$ oc login -u k.admin -p abcxyz --certificate-authority=/tmp/a.crt --insecure-skip-tls-verify=true
$ oc new-project test

1 điểm khác biệt nữa của OpenShift với Kubernetes là các Container của OpenShift hầu như là chạy với user thường.

Do image postgres được build chạy với user 999 nên phải gán quyền cho container được chạy và được truy cập đến nfs

-Tạo và gán quyền truy cập đến nfs
Tạo 1 service account đặt tên là “mytest”

$ oc create serviceaccount mytest -n test

Tạo 1 scc, với nội dung sau: file /tmp/scc999.yaml

# Create SCC for Postgres resources
kind: SecurityContextConstraints
apiVersion: security.openshift.io/v1
metadata:
  name: scc999
allowPrivilegedContainer: true
runAsUser:
  type: MustRunAs
  uid: 999
seLinuxContext:
  type: RunAsAny
fsGroup:
  type: RunAsAny
supplementalGroups:
  type: RunAsAny
$ oc create -f /tmp/scc999.yaml

Gán scc999 cho service account mytest

$ oc adm policy add-scc-to-user scc999 -z mytest -n test

-Tạo deployment: tạo file postgres_deployment_version_limit_resource.json với nội dung dạng template sau:

{
  "apiVersion": "v1",
  "kind": "Template",
  "labels": {
    "template": "postgres-deployment-template"
  },
  "metadata": {
    "name": "postgres-deployment-template"
  },
  "objects": [
    {
      "kind": "Deployment",
      "apiVersion": "apps/v1",
      "metadata": {
        "name": "${PNAME}-${NAME}",
        "labels": {
          "name": "${PNAME}-${NAME}"
        }
      },
      "spec": {
        "replicas": 1,
        "selector": {
          "matchLabels": {
            "app": "${PNAME}-${NAME}"
          }
        },
        "template": {
          "metadata": {
            "labels": {
              "app": "${PNAME}-${NAME}"
            }
          },
          "spec": {
            "containers": [
              {
                "name": "${PNAME}-${NAME}",
                "image": "docker.io/library/postgres:${VERSION}",
                "ports": [
                  {
                    "containerPort": 5432,
                    "protocol": "TCP"
                  }
                ],
                "env": [
                  {
                    "name": "POSTGRES_PASSWORD",
                    "value": "${POSTGRES_PASSWORD}"
                  }
                ],
                "resources": {
                    "limits": {
                       "memory": "16Gi",
                       "cpu": "2000m"
                    },
                    "requests": {
                       "memory": "128Mi",
                       "cpu": "200m"
                    }
                 },
                "volumeMounts": [
                  {
                    "name": "postgres-env",
                    "mountPath": "/var/lib/postgresql/data"
                  }
                ],
                "terminationMessagePath": "/dev/termination-log",
                "imagePullPolicy": "IfNotPresent",
                "securityContext": {
                  "capabilities": {},
                  "runAsUser": 999
                }
              }
            ],
            "volumes": [
              {
                "name": "postgres-env",
                "nfs":
                  {
                     "server": "${SERVER_IP}",
                     "path": "/data/${PNAME}-${NAME}"
                  }
              }
            ],
            "restartPolicy": "Always",
            "dnsPolicy": "ClusterFirst",
            "serviceAccount": "mytest"
          }
        }
      }
    }
  ],
  "parameters": [
    {
      "description": "Project",
      "displayName": "PNAME",
      "name": "PNAME",
      "required": true
    },
    {
      "description": "Ten muon dat",
      "displayName": "NAME",
      "name": "NAME",
      "required": true
    },
    {
      "description": "version db postgres",
      "displayName": "VERSION",
      "name": "VERSION",
      "required": true,
      "value": "14.3"
    },
    {
      "description": "Password postgres",
      "displayName": "POSTGRES_PASSWORD",
      "name": "POSTGRES_PASSWORD",
      "value": "p123"
    },
    {
      "description": "IP's Server nfs share",
      "displayName": "IP's Server nfs share",
      "name": "SERVER_IP"
    }
  ]
}
$ oc process -f /tmp/postgres_deployment_version_limit_resource.json -p PNAME=test -p VERSION=15.1 -p NAME=testdb -p SERVER_IP=192.168.100.53 | oc create -f -
>deployment.apps/test-testdb created

-Expose service: tạo file postgres_svc_ip_expose.json với nội dung dạng template sau:

{
  "apiVersion": "v1",
  "kind": "Template",
  "labels": {
    "template": "postgres-svc-template"
  },
  "metadata": {
    "name": "postgres-svc-template"
  },
  "objects": [
    {
      "apiVersion": "v1",
      "kind": "Service",
      "metadata": {
        "name": "${PNAME}-${NAME}",
        "labels": {
          "app": "${PNAME}-${NAME}"
        }
      },
      "spec": {
        "selector": {
          "app": "${PNAME}-${NAME}"
        },
        "ports": [
          {
            "protocol": "TCP",
            "port": "${{PORT}}",
            "targetPort": 5432
          }
        ],
        "externalIPs": [
          "${IP_EXPOSE1}",
          "${IP_EXPOSE2}"
        ]
      }
    }
  ],
  "parameters": [
    {
      "description": "Project",
      "displayName": "PNAME",
      "name": "PNAME",
      "required": true
    },
    {
      "description": "Ten muon dat",
      "displayName": "NAME",
      "name": "NAME",
      "required": true
    },
    {
      "description": "PORT",
      "displayName": "PORT",
      "name": "PORT",
      "value": "5432",
      "required": true
    },
    {
      "description": "externalIP1",
      "displayName": "externalIP1",
      "name": "IP_EXPOSE1",
      "value": "192.168.99.64"
    },
    {
      "description": "externalIP2",
      "displayName": "externalIP2",
      "name": "IP_EXPOSE2",
      "value": "192.168.99.65"
    }
  ]
}
$ oc process -f /tmp/postgres_svc_ip_expose.json -p PNAME=test -p NAME=testdb -p PORT=5499 | oc create -f -
>service/test-testdb created

Lưu ý: mấy file dạng template khi đã test chạy ổn định rồi thì có thể build nó ra template để sau này tạo mấy database postgres mới mà không cần các file json

-Thử kết nối vào db mới tạo:

$ psql -h 192.168.99.64 -p 5499 -U postgres postgres
Password for user postgres:
psql (14.3, server 15.1 (Debian 15.1-1.pgdg110+1))
WARNING: psql major version 14, server major version 15.
         Some psql features might not work.
Type "help" for help.

postgres=#

Như vậy đã xong phần số 3 và hiện thời là 2 giờ sáng…

Hãy đón đọc bài tiếp theo “PRIVATE CLOUD OPENSHIFT – P4: Ingress”

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ