一.新增自動上 letsencrypt 功能:
這樣以後在router加個annotation -> kubernetes.io/tls-acme : true 就會自動上letsencrypt憑證了。
參考:
https://developer.ibm.com/tutorials/secure-red-hat-openshift-routes-with-lets-encrypt/
https://github.com/tnozicka/openshift-acme/tree/master/deploy#cluster-wide
https://www.redhat.com/en/blog/dynamic-ssl-certificates-using-letsencrypt-openshift
就算不是cluster admin,也可以在自已的專案內使用,比較麻煩的就是每個專案都要佈署進去一次,這裡採的是用cluster wide的方法,必須是cluster admin才行,這樣後以每個使用者就不用自已再做一次,直接上annotation就行。
做法(使用cluster admin):
1.用cluster admin -> oc login
2.執行以下命令:
$ oc new-project acme-operator
$ oc apply -fhttps://raw.githubusercontent.com/tnozicka/openshift-acme/master/deploy/single-namespace/{role,serviceaccount,issuer-letsencrypt-live,deployment}.yaml
$ oc create rolebinding openshift-acme --role=openshift-acme --serviceaccount="$( oc project -q ):openshift-acme" --dry-run -o yaml | oc apply -f -
二.設定default sotrage class:
這樣以後佈署服務時,有掛volume的話,就不用再手動指定storage class,而會自動使用預設的storage class,否則之前都要手動改PVC的yml去指定:
$ sed -i '/spec:/a\ storageClassName: managed-nfs-storage' configs/*-persistentvolumeclaim.yaml
參考
https://www.goglides.dev/bkpandey/how-to-configure-default-storage-class-in-openshift-2oj4
$oc patch storageclass managed-nfs-storage -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'
三.掛載 image registry 的 PV (persistent volume):
預設佈署完 OCP內建的 image registry是沒有作用的,因為沒有指定PV(persistent volume)給他,這樣一些功能是無法正常使用的,譬如build config (在OCP上build image),這包含了S2I (source to image)及build from dockerfile等功能,因此要先給他一個PV才能正常運作。
參考
https://www.ibm.com/docs/zh-tw/mas-cd/continuous-delivery?topic=requirements-enabling-openshift-internal-image-registry
https://access.redhat.com/documentation/en-us/openshift_container_platform/4.3/html/registry/setting-up-and-configuring-the-registry#registry-configuring-storage-baremetal_configuring-registry-storage-baremetal
https://access.redhat.com/documentation/en-us/red_hat_openshift_container_storage/4.2/html-single/managing_openshift_container_storage/index#configuring-image-registry-to-use-openshift-container-storage_rhocs
假設要掛到某個名稱為managed-nfs-storage的storage class,因為是nfs,所以要先確認nfs server上的mount option有no_wdelay 還有 root_squash (但root_squash我沒有加就是了):
# cat /etc/exports
/mnt/data *(rw,sync,no_wdelay,root_squash,insecure,fsid=0)
# systemctl restart nfs-server
再下指令:
$ oc project openshift-image-registry
$ oc create -f <(echo '{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "image-registry-storage"
},
"spec": {
"storageClassName": "managed-nfs-storage",
"accessModes": [ "ReadWriteMany" ],
"resources": {
"requests": { "storage": "100Gi"
}
}
}
}');
================
$ oc edit configs.imageregistry.operator.openshift.io -n openshift-image-registry
======== 手動修改 ========
spec:
managementState: Managed
storage:
pvc:
claim: image-registry-storage
========================
$ oc get co image-registry
===================================================
也有把PVC先掛到暫存空間的方法,但是不建議用在production的服務上:
https://serverfault.com/questions/1082295/how-to-enable-local-image-registry-on-openshift-single-node-cluster-installation
.........
managementState: Managed
..........
replica: 1
...........
storage:
emptyDir: {}
==================
之後看要不要把image registry公開到網路上(也就是建立一個route),可以用預設的DefaultRoute或是自已手動建一個route:
https://access.redhat.com/documentation/en-us/openshift_container_platform/4.8/html/registry/securing-exposing-registry
然後讓要可以登入的使用者新增role:
https://access.redhat.com/documentation/en-us/openshift_container_platform/4.8/html/registry/accessing-the-registry#prerequisites
$ oc project openshift-image-registry
$ oc policy add-role-to-user registry-viewer <user_name>
$ oc policy add-role-to-user registry-editor <user_name>
之後登入(用docker或podman都行)
$ oc whoami -t #先取得登入token,注意不是直接打使用者密碼登入!
$ podman login image-registry.your-opensfhit.domain
Username:<username>
Password:<剛取得的 token>
四.將ingress operator的default controller改用proxy protocol (haproxy也要同時修改):
這樣的好處是pod服務內的程式不但可以從X-Forward-For抓到真實的來源IP,也可以在router下annotation做IP的白名單whitelist,真的是太方便了!
參考:
https://docs.openshift.com/container-platform/4.8/networking/ingress-operator.html#nw-ingress-controller-configuration-proxy-protocol_configuring-ingress
https://www.haproxy.com/documentation/hapee/latest/load-balancing/client-ip-preservation/enable-proxy-protocol/
指令:
$ oc -n openshift-ingress-operator edit ingresscontroller/default
找到最上層的spec (注意不要加到status去了),加入:
spec:
endpointPublishingStrategy:
hostNetwork:
protocol: PROXY
type: HostNetwork
再到 haproxy 的機器,修改 /etc/haproxy/haproxy.cfg,在 listen 或 backend 端的80, 443的server instruction加入send-proxy,mode tcp不用動,這樣就會以proxy protocol溝通(也就是每個連線會加入proxy協定自已的特殊header):
listen ingress-router-443
bind *:443
mode tcp
balance source
server worker0 worker0.example.com:443 check inter 1s send-proxy
server worker1 worker1.example.com:443 check inter 1s send-proxy
server worker2 worker2.example.com:443 check inter 1s send-proxy
接下來可以佈署一個簡單的網頁服務,印出header看看有沒有X-Forwarded-For帶真實IP。
router做白名單的方法:
https://docs.openshift.com/container-platform/4.8/networking/routes/route-configuration.html#nw-route-specific-annotations_route-configuration
在要限制IP的router加入annotation(IP或網段都可以,用space隔開):
haproxy.router.openshift.io/ip_whitelist: 168.85.1.1 203.22.5.0/8
================================
另外關於佈署服務:
一、imagePullPolicy
https://docs.openshift.com/container-platform/4.8/openshift_images/managing_images/image-pull-policy.html
規則如下:
If the tag is latest, OpenShift Container Platform defaults imagePullPolicy to Always.
Otherwise, OpenShift Container Platform defaults imagePullPolicy to IfNotPresent.
但是呢,實際上並不是這麼回事,即使image的tag是latest,他還是不會自動拉新的image,還是會一直使用cache裡面的,真的很困擾,因此每次佈署時,最好手動改一下deploy檔:
$ sed -i '/\ image:/a\ imagePullPolicy: Always' configs/*-deployment.yaml
二、kompose轉換為opensfhit的佈署檔而不是k8s
kompose convert加參數--provider openshift並用 oc apply -f 佈署
https://kubernetes.io/docs/tasks/configure-pod-container/translate-compose-kubernetes/#openshift-kompose-convert-example
但實際上用會有些轉不太完整,
如image stream的設定檔*.imagestream.yaml要手動加 spec.tag.name(image的tag號,應該是bug)
不支援docker compose file的 extra_hosts 參數,得要自已在*.deploymentconfig.yaml的spec.template.spec 手動加:
hostAliases:
- ip: "100.1.2.3"
hostnames:
- "myhost.domain.com"
反而不加--provider openshift參數並改用 kubectl apply -f 倒是沒啥問題...
三、讓container集中在一個pod,而不是一個container就一個pod
可以在kompose convert加參數 --multiple-container-mode 試試
https://github.com/kubernetes/kompose/pull/1394?source=post_page-----20ce5313be1e--------------------------------
四、關於pod運行時的一些權限問題
https://ithelp.ithome.com.tw/articles/10243781
由於OCP對容器的限制比k8s嚴格,不准容器內直接用root(uid= 0 或 root)去執行,而是會隨機給一個UID,但給予的GID是屬於root group的(gid= 0 或 root),因此寫dockerfile時,最好把會動到的目錄(如寫入log 或 tmp 或安裝 plugin檔等的目錄,就是有可能寫入或動到檔案的地方):
RUN chgrp -R 0 /some/directory \
&& chmod -R g+rwX /some/directory
docker compose file的service 可以加入user來指定使用者跟群組:
https://docs.docker.com/compose/compose-file/05-services/#user
如在service下面指定
user: 0:0
或
user: root:root
但這在 openshift 是沒用的,因為就是不允許 root 去跑...
那如果硬要使用image預設指定的user去跑呢?那就要先在專案建一個SA(service account),再把anyuid這個scc policy指定給SA,然後在專案config寫入指定SA:
#用 admin 執行 (一次就好)
oc project my-project
oc create sa my-sa
oc adm policy add-scc-to-user anyuid -z my-sa
#用 user 執行patch (每次重deploy都要)
oc patch dc gitlab -p '{"spec":{"template":{"spec":{"serviceAccountName": "gitlab-sa"}}}}'
#或手動加到deploymentconfig.yaml (每次重deploy都要)
spec:
template:
spec:
serviceAccountName: my-sa
五、關於 coredns 查詢dns時的問題
用以下指令,可發現 cluster的dns ip 固定為 172.30.0.10:
oc get svc -n openshift-dns dns-default -o wide
用172.30.0.10去查,有時會出現 "truncated, retrying in tcp mode":
dig xxx.test.domain @172.30.0.10
nslookup xxx.test.domain 172.30.0.10
再根據以下二篇文章說明,可知dns查詢時,若是回傳的資訊量太大(>512),可能就會由UDP查詢變為TCP查詢,因此會出現 "truncated, retrying in tcp mode"是正常的,不是壞掉:
https://bugzilla.redhat.com/show_bug.cgi?id=2043046#c3
https://bugzilla.redhat.com/show_bug.cgi?id=2062307#c14
因此去檢查upstream的dns server時,發現 53/TCP 竟然沒監聽,只剩下 53/UDP,因此把bind給重啟就好了,只是怎麼會掛掉…蠻神奇的。
六、Ingress Controller 數量不夠的問題
參照:
https://access.redhat.com/discussions/5490621#comment-2288691
https://access.redhat.com/documentation/zh-tw/openshift_container_platform/4.5/html/networking/configuring-ingress-controller#nw-ingress-controller-configuration_configuring-ingress
單位的openshift平台配置了六個node,master x 3(作為api的管理pod用),worker x 3(作為使用者專案產生的pod運行)。
某天查haproxy的log時,發現有以下訊息:
localhost haproxy[3679]: Server ingress-router-80/worker0 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 2 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
表示worker0的haproxy(也是就ingress controller)沒在跑,因此80/443都被refused,netstate去檢查80/443也沒有程式在監聽,用以下指令查目前的ingress controller的replicas數量:
$ oc get -n openshift-ingress-operator ingresscontrollers/default -o jsonpath='{$.status.availableReplicas}'
發現數量只有2,但有3台worker,數量當然不夠,因此增加replica的數量:
$ oc patch -n openshift-ingress-operator ingresscontroller/default --patch '{"spec":{"replicas": 3}}' --type=merge
設定haproxy log的方法:https://linuxconfig.org/install-and-configure-haproxy-on-redhat-8