---
# System prepended metadata

title: home lab OCP 4.11

---

# home lab OCP 4.11
## Bastion 
### DNS server
``` bash=
$ dnf install -y bind bind-utils
$ vi /etc/named.conf
---
acl clients {0.0.0.0/0;};
options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { any; };
        directory       "/var/named";
        ...
        allow-query     { localhost; clients; };
        ...
}
...
include "/etc/named/home.lab.zones";
---
$ vi /etc/named/home.lab.zones
---
//forward zone
zone "home.lab" IN {
        type master;
        file "home.lab.zone";
        allow-update { none; };
};

//backward zone
zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "1.168.192.zone";

};
---
$ vi /var/named/home.lab.zone
---
$TTL    86400
@        IN     SOA     dns.home.lab.   admin.home.lab (
                42         ; serial
                3H         ; refresh
                15M        ; retry
                1W         ; expiry
                1D )       ; minimum
;
                        IN NS           dns.home.lab.
registry                IN A            192.168.1.100
dns                     IN A            192.168.1.100
api.ocp4                IN A            192.168.1.100
api-int.ocp4            IN A            192.168.1.100
*.apps.ocp4             IN A            192.168.1.100
master-1.ocp4           IN A            192.168.1.101
master-2.ocp4           IN A            192.168.1.102
master-3.ocp4           IN A            192.168.1.103
bootstrap.ocp4          IN A            192.168.1.104
infra-1.ocp4            IN A            192.168.1.105
---
$ chown root:named /var/named/home.lab.zone
$ chmod 640 /var/named/home.lab.zone
$ vi /var/named/1.168.192.zone
---
$TTL    86400
@       IN      SOA             dns.home.lab.   root.home.lab. (
                1997022700      ; serial
                28800           ; refresh
                14400           ; retry
                3600000         ; expire
                86400           ; minimum
)
        IN      NS      dns.home.lab.
;
101     IN      PTR     master-1.ocp4.home.lab.
102     IN      PTR     master-2.ocp4.home.lab.
103     IN      PTR     master-3.ocp4.home.lab.
104     IN      PTR     bootstrap.ocp4.home.lab.
105     IN      PTR     infra-1.ocp4.home.lab.              
---
$ chown root:named /var/named/1.168.192.zone
$ chmod 640 /var/named/1.168.192.zone
$ named-checkzone home.lab /var/named/home.lab.zone
$ named-checkzone 1.168.192.in-addr.arpa /var/named/1.168.192.zone
$ systemctl start named
$ systemctl enable named
$ firewall-cmd --add-service=dns --permanent
$ firewall-cmd --reload
```
### NTP server
``` bash=
$ vi /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (https://www.pool.ntp.org/join.html).
#server time.stdtime.gov.tw
#server tock.stdtime.gov.tw
...
# Allow NTP client access from local network.
allow 192.168.1.0/24

# Serve time even if not synchronized to a time source.
local stratum 3
...
$ systemctl enable chronyd --now
```



### HAProxy
```bash!=
$ dnf install haproxy
$ semanage port --add --type http_port_t --proto tcp 22623
$ semanage port --add --type http_port_t --proto tcp 6443
$ semanage port -l | grep http_port_t
http_port_t                    tcp      6443, 22623, 80, 81, 443, 488, 8008, 8009, 8443, 9000
$ vi  /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
  log         127.0.0.1 local2
  pidfile     /var/run/haproxy.pid
  maxconn     4000
  daemon

defaults
  mode                    http
  log                     global
  option                  dontlognull
  option http-server-close
  option                  redispatch
  retries                 3
  timeout http-request    10s
  timeout queue           1m
  timeout connect         10s
  timeout client          1m
  timeout server          1m
  timeout http-keep-alive 10s
  timeout check           10s
  maxconn                 3000

frontend stats
  bind *:9000
  mode            http
  log             global
  maxconn 10
  stats enable
  stats hide-version
  stats refresh 30s
  stats show-node
  stats show-desc Stats for ocp4 cluster
  stats auth admin:ocp4
  stats uri /stats

frontend openshift-api-server
  bind *:6443
  default_backend openshift-api-server
  mode tcp
  option tcplog

backend openshift-api-server
  balance source
  mode tcp
  server master-1 192.168.1.101:6443 check
  server master-2 192.168.1.102:6443 check
  server master-3 192.168.1.103:6443 check
  #server bootstrap 192.168.1.104:6443 check

#---------------------------------------------------------------------
frontend machine-config-server
  bind *:22623
  default_backend machine-config-server
  mode tcp
  option tcplog

backend machine-config-server
  balance source
  mode tcp
  server master-1 192.168.1.101:22623 check
  server master-2 192.168.1.102:22623 check
  server master-3 192.168.1.103:22623 check
  #server bootstrap 192.168.1.104:22623 check

#---------------------------------------------------------------------
frontend ingress-http
  bind *:80
  default_backend ingress-http
  mode tcp
  option tcplog

backend ingress-http
  balance source
  mode tcp
  server infra-1 192.168.1.105:80 check
  server infra-2 192.168.1.106:80 check

#---------------------------------------------------------------------
frontend ingress-https
  bind *:443
  default_backend ingress-https
  mode tcp
  option tcplog

backend ingress-https
  balance source
  mode tcp
  server infra-1 192.168.1.105:443 rcheck
  server infra-2 192.168.1.106:443 check

```
### Registry
``` bash=
$ dnf install -y httpd-tools #htpasswd
$ export MAIN_DIR=/opt/registry
$ mkdir -p $MAIN_DIR/{auth,certs,data,conf}
$ htpasswd -bBc $MAIN_DIR/auth/htpasswd admin redhat
$ semanage fcontext -a -t container_file_t '/opt/registry/(auth|certs|data|conf)(/.*)?'
$ semanage fcontext -l | grep '/opt/registry'
$ restorecon -Rv /opt/registry
$ podman run -d -p 5000:5000 --restart=always --name registry \
  -v $MAIN_DIR/conf:/etc/docker/registry \
  -v $MAIN_DIR/data:/var/lib/registry \
  -v $MAIN_DIR/auth:/auth \
  -e "REGISTRY_STORAGE_DELETE_ENABLED=true"
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v $MAIN_DIR/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
  registry:2
$ podman generate systemd --new --files --name registry
$ cp -Z container-registry.service /etc/systemd/system
$ systemctl daemon-reload 
$ systemctl enable --now container-registry.service
```
### web server
``` bash=
$ dnf install httpd
$ vi /etc/httpd/conf/httpd.conf
...
Listen 8080
...
$ systemctl enable httpd --now
```
### NFS server
#### 安裝nfs相關套件
```shell=
$ dnf install -y nfs-utils rpcbind
```
#### 啟動nfs相關服務
```shell=
$ systemctl enable rpcbind --now
$ systemctl enable nfs-server --now
$ systemctl status rpcbind
$ systemctl status nfs-server
```
#### 目錄建立權限設定
建立nfs share dir
```shell=
$ mkdir /opt/nfs
$ chmod -R 755 /opt/nfs
$ chown -R 1000:1000 /opt/nfs
```
#### nfs service 分享目錄設定
``` bash=
$ vi /etc/exports
/opt/nfs 192.168.1.0/24(rw,sync,no_root_squash,all_squash,anonuid=1000,anongid=1000)
```
執行以下命令套用
```shell=
$ exportfs -arv
$ showmount -e localhost
```
#### 設定SELinux

```shell=
$ setsebool -P nfs_export_all_rw on
$ setsebool -P nfs_export_all_ro on
```

### firewall 
``` bash=
$ firewall-cmd --add-service={dns,http,https,ntp,mountd,rpc-bind,nfs} --permanent
$ firewall-cmd --add-port={22623,6443,8080,5000,9000}/tcp --permanent
$ firewall-cmd --reload
$ firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources:
  services: dhcpv6-client dns http https ntp ssh
  ports: 22623/tcp 6443/tcp 8080/tcp 5000/tcp 9000/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```
## ocp 檔案準備
### 同步Redhat ocp image 至本地目錄
>帶有pull-secret.json，及可連線至外網機器，並安裝oc
> rhcos.raw.gz
``` bash=
## 查看registry info
$ oc adm release info -a pull-secret.json quay.io/openshift-release-dev/ocp-release:4.11.21-x86_64
$ mkdir mirror
$ oc adm -a pull-secret.json release mirror   --from=quay.io/openshift-release-dev/ocp-release:4.11.21-x86_64   --to-dir=mirror/
$ tar zcvf mirror.tar.gz mirror #產生mirror.tar.gz檔
```
### Bastion oc Client 安裝
> openshift-client-linux-4.11.21.tar.gz
> openshift-install-linux-4.11.21.tar.gz
> oc-mirror.tar.gz
> pull-secret.txt
``` bash=
$ tar xvzf openshift-client-linux-4.11.21.tar.gz
$ tar xvzf openshift-install-linux-4.11.21.tar.gz
$ tar xvzf oc-mirror.tar.gz
$ install openshift-install /usr/local/bin/openshift-install
$ install oc                /usr/local/bin/oc
$ install kubectl           /usr/local/bin/kubectl
$ install oc-mirror         /usr/local/bin/oc-mirror
## 設定 Bash Completion ，提供自動補完，執行完，需重新登入 bash。
$ dnf install bash-completion
$ oc         completion bash > /etc/bash_completion.d/oc
$ kubectl    completion bash > /etc/bash_completion.d/kubectl
$ oc-mirror  completion bash > /etc/bash_completion.d/oc-mirror
```
### Bastion同步本地ocp image 至 Private Registry
> 帶入mirror.tar.gz、pull-secret.json
``` bash=
## base64加密自建registry user:pass
$ echo -n admin:redhat | base64
<base64 admin:redhat>
## 依照 pull-secret.json 加入
$ vi pull-secret.json
{
  "auths": {
    ...
    "registry.home.lab": {
      "auth": "<base64 admin:redhat>"
    }
  }
}
## 配置同步registry變數
$ LOCAL_SECRET_JSON='pull-secret.json'
$ OCP_RELEASE=4.11.21-x86_64
$ LOCAL_REGISTRY='registry.home.lab:5000'
$ LOCAL_REPOSITORY="ocp4/release"
$ tar xvzf mirror.tar.gz
$ oc image mirror -a ${LOCAL_SECRET_JSON}   --from-dir=mirror/ "file://openshift/release:"${OCP_RELEASE}"*"   ${LOCAL_REGISTRY}/${LOCAL_REPOSITORY}   --insecure
```
### 建立CoreOS node key
``` bash=
$ ssh-keygen -t rsa -b 4096 -N '' -f ~/ocp_ssh_key.pub
```
### 配置安裝源
> 於Redhat官方下載帶入rhcos.raw.gz
``` bash=
## 準備自建registry crt
## 帶入pull-secret.json
## 網域名 -> DOMAIN
## 集群名 -> CLUSTERID
## Registry url -> REGISTRY_URL
## Registry 憑證內容 -> REGISTRY_CRT
## core os key -> OCP_SSH_KEY
## pull-secret.json內容 PULL_SECRETsecret.json
$ vi ~/install-config.yaml 
apiVersion: v1
baseDomain: ${DOMAIN}      #<- 根據自我環境定義
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 0
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: ${CLUSTERID}       #<- 根據自我環境定義
networking:
  clusterNetworks:
  - cidr: 10.92.0.0/16     #<- 根據自我環境定義
    hostPrefix: 23         #<- 根據自我環境定義 
  networkType: OpenShiftSDN
  serviceNetwork:
  - 10.251.0.0/16          #<- 根據自我環境定義
platform: 
  none: {}
pullSecret: '${PULL_SECRET}'
sshKey: '${OCP_SSH_KEY}'
additionalTrustBundle: |
${ROOT_CA}
imageContentSources:
- mirrors:
  - ${REGISTRY_URL}
  source: quay.io/openshift-release-dev/ocp-release
- mirrors:
  - ${REGISTRY_URL}
  source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
$ export DOMAIN=home.lab
$ export CLUSTERID=ocp4
$ export PULL_SECRET=$(cat ~/pull-secret.json)
$ export OCP_SSH_KEY=$(cat ~/ocp_ssh_key.pub)
$ export ROOT_CA=$(sed 's/^/  /g' /etc/pki/ca-trust/source/anchors/root_CA.crt)
$ export REGISTRY_URL=registry.home.lab:5000/ocp4/release
$ envsubst < install-config.yaml > ./install/install-config.yaml
$ mkdir install
$ cd ./inastll
$ openshift-install create manifests
$ cat manifests/cluster-scheduler-02-config.yml # 檢查mastersSchedulable是否為true
$ sed -i 's/mastersSchedulable: true/mastersSchedulable: false/g' manifests/cluster-scheduler-02-config.yml
$ cat manifests/cluster-scheduler-02-config.yml # 檢查mastersSchedulable為false
$ openshift-install create ignition-configs
$ tree ./ #確認生成以下檔案
./
├── auth
│   ├── kubeadmin-password
│   └── kubeconfig
├── bootstrap.ign
├── master.ign
├── metadata.json
└── worker.ign
$ mkdir /var/www/html/ocp4
$ cp *.ign /var/www/html/ocp4
$ cat >> /var/www/html/install.sh
#!/bin/sh

set -x

export BASTION_IP=192.168.1.100:8080

sudo coreos-installer install /dev/sda \
  --insecure \
  --insecure-ignition \
  -u http://${BASTION_IP}/ocp4/rhcos.raw.gz \
  -I http://${BASTION_IP}/ocp4/${CLUSTER_ROLE}.ign \
  --firstboot-args 'rd.neednet=1' \
  --copy-network
<ctrl+D>
$ chown apache:apache -R /var/www/html/
$ restorecon -Rv /var/www/html/nvn 
```
## 安裝Openshift 集群
### bootstrap 安裝
``` shell=
$ nmtui #配置網路
$ curl -O http://192.168.1.100:8080/install.sh
$ chmod 755 install.sh
$ CLUSTER_ROLE=bootstrap ./install.sh
# 從Bastion ssh bootstrap
$ ssh -i ~/ocp_ssh_key core@192.168.1.101
$ journalctl -b -f -u bootkube.service #看安裝情形
```
### master 安裝
``` shell=
$ nmtui #配置網路
$ curl -O http://192.168.1.100:8080/install.sh
$ chmod 755 install.sh
$ CLUSTER_ROLE=master ./install.sh
```
### 安裝進度
以下步驟，可查看 OCP 安裝的進度

1. 登入bootstrap執行以下指令，查看安裝log

```shell=
$ sudo journalctl -b -f -u release-image.service -u bootkube.service
```

2. 登入bastion使用以下指令，確認 Master 節點已加入叢集

```shell=
$ sudo oc --kubeconfig=?/kubeconfig get node -w 
$ openshift-install wait-for bootstrap-complete --dir=./openshift4/ignition --log-level debug
```

### 安裝Worker node
``` shell=
$ nmtui #配置網路
$ curl -O http://192.168.1.100:8080/install.sh
$ chmod 755 install.sh
$ CLUSTER_ROLE=worker ./install.sh
```
### 新增Worker node
>到Bastion node
全部一併 Approve (至少須執行2次以上)
``` shell=
$ oc get csr | grep 'Pending' | awk '{print $1}' | xargs -n 1 oc adm certificate approve #審核Pending csr
```
### 設定bastion ssh 快速登入
>以root使用者為例
``` bash=
$ cp ~/ocp_ssh_key ~/.ssh/
$ cat >> ~/.ssh/config
Host *.ocp4.home.lab
  User core
  IdentityFile /root/.ssh/ocp_ssh_key

Host 192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104 192.168.1.105 192.168.1.106 192.168.1.107 192.168.1.108
  User core
  IdentityFile /root/.ssh/ocp_ssh_key
$ ssh 192.168.1.101 #可直接ssh
```
### 設定 NTP (chrony)
準備 RHCOS 用的 MachineConfig
``` shell=
$ vi ./chrony-template.yaml
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: ${MC_ROLE}
  name: 99-${MC_ROLE}s-chrony-configuration
spec:
  config:
    ignition:
      config: {}
      security:
        tls: {}
      timeouts: {}
      version: 3.1.0
    networkd: {}
    passwd: {}
    storage:
      files:
      - contents:
          source: data:text/plain;charset=utf-8;base64,${CHRONY_BASE64}
        mode: 420
        overwrite: true
        path: /etc/chrony.conf
  osImageURL: ""
```
### 套用 Machine Config
>產生Machine Config 並 apply 到 OCP 上
此步驟將會重開對應的 OCP 節點
``` shell=
$ cat >> ./chrony.conf
server 192.168.1.100 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
$ export CHRONY_BASE64=$(cat ./chrony.conf | base64 -w 0)
$ export MC_ROLE="master" 
$ envsubst < chrony-template.yaml > chrony-${MC_ROLE}.yaml
$ export MC_ROLE="worker" 
$ envsubst < chrony-template.yaml > chrony-${MC_ROLE}.yaml
$ oc apply -f chrony-master.yaml
$ oc apply -f chrony-worker.yaml
```
### 設定 Node Label

#### 設定 infra/router/logger 的 node labels

```shell=
$ oc label node <infra-node>  node-role.kubernetes.io/infra=""
$ oc label node <worker-node> node-role.kubernetes.io/app=""
```

#### 設定 Machine Config Pool

> 建立 `infra-mcp.yaml`

```yaml=
# Remember at vi `set paste`
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfigPool
metadata:
  name: infra
spec:
  machineConfigSelector:
    matchExpressions:
    - key: machineconfiguration.openshift.io/role
      operator: In
      values:
      - worker
      - infra
  nodeSelector:
    matchLabels:
      node-role.kubernetes.io/infra: ""
```

> 建立新的 Machine Config Pool  
> **注意，此步驟將會重開對應的 OCP 節點**

```shell=
$ oc apply -f infra-mcp.yaml
$ oc get mcp
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
infra    rendered-infra-883f99ee56ac656339dff82b4036ca46    True      False      False      2              2                   2                     0                      5m12s
master   rendered-master-a08cefca086c4f3dd0f97d8f47caae11   True      False      False      3              3                   3                     0                      14d
worker   rendered-worker-883f99ee56ac656339dff82b4036ca46   True      False      False      0              0                   0                     0                      14d
```

#### 移除多餘的 worker labels

> 記得先設定 Machine Config Pool ，並確認都更新完成  
> **此步驟將會重開對應的 OCP 節點**

```shell=
$ oc label node <infra-node>  node-role.kubernetes.io/worker-
```
### Router 設定

> 將 router 元件，綁定執行位置到 infra node 上 (nodePlacement) 並設定執行個數 (replicas)

```shell=
$ oc edit IngressController default -n openshift-ingress-operator
...
spec:
  nodePlacement:
    nodeSelector:
      matchLabels:
        node-role.kubernetes.io/infra: ""
  replicas: 2
  
$ oc -n openshift-ingress get pod -o wide
```
### Web Console 存取
``` bash=
$ oc -n openshift-console get route console -o=jsonpath='{.spec.host}{"\n"}'
console-openshift-console.apps.ocp4.home.lab
```
### 離線 Operator Marketplace 設定

> **注意，記得修改 yaml 裡面的 URL ，以符合環境** 

> **注意，記得修改 yaml 裡面的 URL ，以符合環境**

#### 移除對外的 OperatorHub

> 移除之前

```shell=
$ oc -n openshift-marketplace get po
```

![](https://i.imgur.com/wRIwPGa.png)

> 移除之後

```shell=
$ oc patch OperatorHub cluster --type json -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'
$ oc -n openshift-marketplace get po
```

![](https://i.imgur.com/BHSweqv.png)

#### 下載外部OperatorHub 相關image
> **可連外網機器先決條件**
> podman version 1.9.3+
> oc-mirror
> pull-secret.json
``` bash=
$ wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.11.21/oc-mirror.tar.gz
$ tar xvzf oc-mirror.tar.gz
$ install oc-mirror /usr/local/bin/oc-mirror
$ mkdir ~/.docker
$ cat pull-secret.json > ~/.docker/config.json
$ oc mirror init > mirror-config.yaml #產生初始化yaml自行修改要mirror的package
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v1alpha2
storageConfig:
  local:
    path: ./
mirror:
  platform:
    channels:
    - name: stable-4.11
      type: ocp
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.12
    packages:
    - name: serverless-operator
      channels:
      - name: stable
  additionalImages:
  - name: registry.redhat.io/ubi8/ubi:latest
  helm: {}
$ oc-mirror --config mirror-config.yaml file://operator-mirror --ignore-history
$ tar zcvf operator-mirror.tar.gz operator-mirror
```
#### 移除對外的 OperatorHub

> 移除之前

```shell=
$ oc -n openshift-marketplace get po
```

![](https://i.imgur.com/wRIwPGa.png)

> 移除之後

```shell=
$ oc patch OperatorHub cluster --type json -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'
$ oc -n openshift-marketplace get po
```
#### 建立離線OperatorHub
>operator-mirror.tar.gz
``` bash=
$ tar xvzf operator-mirror.tar.gz
$ cd operator-mirror
$ oc-mirror --from mirror_seq2_000000.tar docker://registry.home.lab:5000/redhat-operator --skip-metadata-check
$ cd oc-mirror-workspace/results-1673542316
$ oc apply -f catalogSource-redhat-operator-index.yaml
$ oc apply -f imageContentSourcePolicy.yaml
```
### 移除對外更新檢查

> 移除 sample image stream

```shell=
$ oc patch configs.samples.operator.openshift.io cluster --type merge --patch '{"spec":{"managementState":"Removed"}}'

$ oc extract secret/pull-secret -n openshift-config --to=.
$ ls -a
.dockerconfigjson
$ vi .dockerconfigjson #Remove the cloud.openshift.com JSON entry.
$ oc set data secret/pull-secret -n openshift-config --from-file=.dockerconfigjson=.dockerconfigjson
$ oc delete deployment insights-operator -n openshift-insights
```

> 移除 cluster version update

```shell=
$ oc patch clusterversion/version --type=merge --patch '{"spec":{"channel":""}}' 
```
### 設定 NFS Provisioner

- [Reference here](https://hackmd.io/cmrZkn_lTs6vyQjx1ipkaw#Nfs-subdir-external-provisioner)
- [github](https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner)
---
## Operator 安裝

### 1. 登入 web console

使用以下網址登入：  
[https://console-openshift-console.apps.ocp4.home.lab/](https://console-openshift-console.apps.ocp4.home.lab/)

### 2. 搜尋可使用的 Operator

點選 Operators -> OperatorHub -> My Operator

### 3. 安裝 Operator

安裝以下 Operator:

- Local Storage
  - 4.11.0-202212070335 provided by Red Hat
- Loki Operator
  - 5.5.5 provided by Red Hat

(後續安裝，先看下個章節再看本節設定)  
點選 Install -> 勾選以下選項

- Enable `operator recommended cluster monitoring on this namespace`
  - 如果有此選項，才需要勾選
- Approve Strategy -> Manual

### 4. 第一次安裝，需要手動 Approve

點選 Manual approval required -> Approve

---

## Loki 安裝

### Local Storage Operator 安裝

#### 1. 參考文件安裝步驟安裝 Local Storage Operator

> **可參考 [安裝 Operator](#安裝-Operator) 一章**

安裝以下 Operator:

- Local Storage
  - 4.6.0-202106010807.p0.git.fa3468d provided by Red Hat

```
https://docs.openshift.com/container-platform/4.6/storage/persistent_storage/persistent-storage-local.html#local-storage-install_persistent-storage-local
```

#### 2. 設定 nodeSelector

```shell=
$ oc annotate ns openshift-local-storage openshift.io/node-selector=""
```

#### 3. 建立 Local Volume

- 建立檔案 `~/ocp_config/efk.localvolume.yaml`

```yaml=
apiVersion: "local.storage.openshift.io/v1"
kind: "LocalVolume"
metadata:
  name: "local-efk-disks"
  namespace: "openshift-local-storage"
spec:
  nodeSelector:
    nodeSelectorTerms:
    - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - <logger-node-1> # oc get node, label = logger
          - <logger-node-2>
          - <logger-node-3>
  storageClassDevices:
    - storageClassName: "local-efk-sc"
      volumeMode: Filesystem
      fsType: xfs
      devicePaths:
        - /dev/sdb   
```

- 套用 yaml

```shell=
$ oc apply -f efk.localvolume.yaml
```

- 檢查 Disk Maker

```shell=
$ oc -n openshift-local-storage get po
```

![](https://i.imgur.com/VIkyvgi.png)

- 檢查 PV

```shell=
$ oc get pv
```

![](https://i.imgur.com/ccuqeY4.png)

- 檢查 storageclass

```shell=
$ oc get sc
```

![](https://i.imgur.com/051lXME.png)
---