Posted on

如何把docker image推到AKS

請參考此說明: https://docs.docker.com/cloud/aci-integration/

首先請登入Azure

會跳出瀏覽器登入Azure的帳號和docker做連接

docker login azure

接著創立aci的context

docker context create aci myacicontext

使用docker context ls可以檢視現在有哪些context

接著這樣就可以把image部屬上AKS了

docker --context myacicontext run -p 80:80 nginx

推送自建的container

https://learn.microsoft.com/zh-tw/training/modules/intro-to-containers/7-exercise-deploy-docker-image-to-container-instance

1.建立容器

2. 改名並推送上去

docker tag reservationsystem:latest <registry-name>.azurecr.io/reservationsystem:latest
docker image ls
docker login <login-server>
docker push <registry-name>.azurecr.io/reservationsystem:latest
Posted on

軟件定義存儲(Software Defined Storage,SDS)介紹

甚麼是SDS

軟件定義存儲(Software Defined Storage,SDS)是一種存儲技術的方法論,它通過軟件層面的控制和管理來處理存儲資源,使得存儲系統更加靈活、可擴展和易於管理。傳統的存儲系統通常使用專用的硬體設備和控制器來管理數據存儲,而軟件定義存儲採用軟件定義的方法,將存儲處理功能抽象出來,從而使得存儲資源可以根據需要進行分配和管理。

SDS的主要特色

  1. 抽象化:軟件定義存儲將存儲資源的物理特性與控制功能進行解耦,使得存儲資源的管理和配置可以在軟件層面完成,而不依賴於特定的硬體設備。
  2. 集中管理:軟件定義存儲可以通過集中式的管理界面來控制和監控存儲系統,這使得管理人員可以更方便地進行配置、擴展和故障排除。
  3. 彈性擴展:由於軟件定義存儲可以根據需要進行動態配置和管理,因此可以輕鬆地擴展存儲容量和性能,以適應不斷增長的數據需求。
  4. 自動優化:軟件定義存儲通常具有自我優化的功能,它可以根據數據使用情況和需求來自動調整存儲策略,以提供最佳的性能和效率。
  5. 開放性:軟件定義存儲通常基於開放標準和API,這使得它可以與多種硬體設備和存儲平台兼容,並且支援多種存儲協議。

SDS的工作原理

借助軟件定義的存儲,應用程序可以動態配置所需的容量、性能和保護的精確組合——不多也不少。SDS 為存儲帶來了服務器虛擬化為計算帶來的簡單性、效率和成本節約。它允許您消除低效的專用硬件,並使用更靈活、透明和自動化的系統。此外,該存儲解決方案可與現有存儲解決方案和雲配合使用。

SDS軟件通過虛擬數據平面對底層存儲進行抽象;這使得虛擬機(和應用程序)成為存儲配置和管理的基本單元。

通過在應用程序和可用資源之間創建靈活的分離,普及的虛擬機 管理程序 可以平衡應用程序所需的所有 IT 資源(計算、內存、存儲和網絡)。

SDS與Persistent Volumes

SDS(軟件定義存儲)和Kubernetes中的Persistent Volumes(持久化存儲卷)是相關的概念,它們都涉及到在容器化環境中對存儲資源的管理。

Kubernetes是一個用於容器化應用程序管理和部署的開源平台,而Persistent Volumes(PV)是Kubernetes中用於持久化存儲的抽象層。PV允許將持久化存儲資源(例如Amazon EBS、Google Persistent Disk、NFS、Ceph等)與Kubernetes集群中的Pod相關聯,從而實現容器應用程序的持久化數據存儲。

Kubernetes的Persistent Volumes(PV)提供了對多種存儲技術的抽象,因此你可以使用多種技術來實現PV。以下是一些常見的PV實現技術:

  1. 主機路徑(HostPath):這是一種簡單的PV實現方式,將宿主機上的目錄掛載為PV。但需要注意的是,這種方式只適合單節點集群,而且缺乏高可用性和故障恢復機制。
  2. NFS(Network File System):NFS是一種分佈式文件系統,可以在多個節點之間共享文件。你可以使用NFS伺服器提供持久化存儲,並將其掛載為Kubernetes中的PV。
  3. iSCSI:iSCSI是一種塊存儲協議,它可以通過網絡將存儲設備映射為本地塊設備。你可以使用iSCSI裝置提供持久化存儲,並將其作為PV掛載到Kubernetes中的Pod中。
  4. Ceph:Ceph是一種分佈式存儲解決方案,它提供對象存儲、塊存儲和文件系統的支持。你可以使用Ceph作為PV提供持久化存儲,這樣可以實現高可用性和可擴展性。
  5. GlusterFS:GlusterFS是一種分佈式文件系統,可以提供高可用性和可擴展性的存儲。你可以使用GlusterFS作為PV,讓Kubernetes中的Pod使用這種分佈式文件系統。
  6. 雲端提供商的持久化存儲服務:如果你在公有雲上運行Kubernetes,大多數雲提供商都提供了專門的持久化存儲服務,例如Amazon EBS(Elastic Block Store)或Google Persistent Disk。你可以使用這些服務來實現PV。

SDS則是一種更廣泛的存儲技術,它可以用來管理和處理各種存儲資源,並提供更高級別的抽象和自動化。在Kubernetes中,PV可以使用SDS技術來實現,例如使用Ceph、GlusterFS等SDS解決方案作為Kubernetes Persistent Volumes的後端存儲。

SDS不一定要是物件存儲服務才算。SDS可以涵蓋多種存儲技術,包括塊存儲、文件存儲和物件存儲等。重要的是,SDS是通過軟件進行存儲管理和控制,而不依賴於特定硬體或供應商

SDS是一種以軟件為基礎的存儲管理方法

SDS(軟件定義存儲)是一種存儲技術的方法論,它通過軟件層面的控制和管理來處理存儲資源,而不是依賴於特定的硬體設備或供應商。這意味著SDS可以在不同的硬體平台上運行,並且可以支援多種存儲技術,如塊存儲、文件存儲和物件存儲等。SDS的目標是提供一個統一的、抽象的存儲管理接口,使得存儲資源的配置、管理和控制可以在軟件層面進行,而不需要直接依賴於特定的硬體或供應商的API。

當談到儲存圖片和影片等數據時,最終這些數據是需要存儲在硬碟上的,而硬碟是物理媒體。SDS並不是指數據直接存在於軟件中,而是指存儲管理和控制的功能在軟件層面進行。

SDS可以使用不同的硬體設備來實現存儲,比如使用傳統硬碟(HDD)、固態硬碟(SSD)、雲端存儲、存儲區域網絡(SAN)等。這些硬體設備提供實際的數據存儲介質,而SDS則通過軟件抽象出這些硬體設備的管理和控制功能。

總的來說,SDS是一種以軟件為基礎的存儲管理方法,它可以在不同的硬體平台上運行,並且可以支援多種存儲技術,但最終數據仍然需要存儲在實際的硬碟或媒體上。

使用SDS來蒐集ML資料的優勢

使用SDS(軟件定義存儲)可以幫助蒐集機器學習(Machine Learning,ML)所需的資料,並且相對於傳統的數據存儲方式,它可能更有利於處理大量數據並提供更好的可擴展性和彈性。

以下是幾個使用SDS來蒐集ML資料的優勢:

  1. 彈性和可擴展性:SDS可以基於軟件進行存儲管理和控制,這意味著你可以方便地擴展存儲容量,並根據需要增加或減少資料存儲的規模。這對於處理大量數據和快速增長的需求是非常有利的。
  2. 多種存儲技術支援:SDS可以支援多種存儲技術,包括物件存儲、塊存儲和文件存儲等。這使得你可以根據不同的數據類型和用途,選擇最合適的存儲技術,而不必局限於單一的存儲方式。
  3. 數據複製和冗余:SDS通常提供數據複製和冗余功能,這可以確保數據的高可用性和持久性。這對於在ML訓練過程中保證數據完整性和可靠性是非常重要的。通常,SDS或存儲系統會提供一些配置選項來控制數據的冗余程度,如副本數量或冗余策略。你可以根據應用的需求,選擇適當的冗余程度,以平衡數據可用性和資源消耗。
  4. 異地備份:SDS還可以支援異地備份,將數據備份到不同的地理位置。這樣即使出現故障或災害,你的數據仍然可以安全地恢復。
  5. 快速數據存取:某些SDS解決方案可以提供高速的數據讀取和寫入性能,這對於需要快速存取大量數據的機器學習訓練是非常重要的。
Posted on

在K8S內ksoftirqd耗費大量CPU

問題描述

我們在K8S內架設串流伺服器,在做loadtest時發現,當流量變高之後,K8S用來管理線程的cadvisor所調用的ksoftirqd會占掉非常大的CPU使用率,並導致整個worker node變得緩慢。

相關的問題說明請見: Debugging network stalls on Kubernetes

形成原因

這是因為當使用 Kubernetes 的 NodePort 來公開一個服務時,它將在每個工作節點上開放一個端口,以便外部可以連接到該端口,並將流量轉發到服務的後端 Pod 上。當流量高峰期間,可能會導致節點的 CPU 負載增加,並導致大量的 IRQ 請求,這是因為每個數據包都會觸發一次 IRQ 請求。

IRQ是甚麼

IRQ 是中斷請求的簡寫,是一種處理設備 I/O 操作的機制。當設備有 I/O 操作時,它會觸發一個中斷請求,通知操作系統或應用程序需要處理這個 I/O 操作。在網絡通信中,每個數據包都會觸發一次 IRQ 請求,因此當流量高峰期間,大量的 IRQ 請求可能會導致節點的 CPU 負載增加,從而影響應用程序的性能。中斷請求通常由外部設備發出,例如鍵盤、鼠標、網卡、磁盤控制器等,這些設備需要與 CPU 進行通信,以便進行數據傳輸、讀寫、處理等操作。

IRQ 的實現通常涉及到硬件和軟件兩個方面。在硬件方面,通常需要在主板上預留一些專門的中斷請求線(IRQ lines),用於連接各種外設和 CPU,以便它們之間進行數據傳輸和通信。一般來說,一個計算機系統會有多個 IRQ lines,每個 IRQ line 對應一個外設或者一組相關的外設。

在軟件方面,操作系統需要通過中斷控制器來管理各個 IRQ lines,以便在接收到外設發出的中斷請求時,及時地響應並處理。一般來說,中斷控制器會將中斷請求轉發給 CPU,CPU 再執行相應的中斷處理程序來處理中斷請求。

IRQ是計算機硬件的設計決定。當網絡適配器(NIC)接收到數據包時,它會發送一個中斷請求(IRQ)給處理器,通知處理器需要處理這個數據包。處理器收到 IRQ 後,會停止當前的任務,並開始處理中斷請求。處理完中斷請求後,處理器會返回到之前的任務繼續執行。.

網絡適配器是什麼

網絡適配器,也稱為網絡接口卡(Network Interface Card,NIC),是計算機中用於實現網絡通信的硬件設備之一。它通常安裝在計算機主板上,負責接收和發送網絡數據包。網絡適配器可以連接到不同類型的網絡,例如以太網、Wi-Fi、藍牙等,以實現不同的網絡通信方式。

網絡適配器在計算機中的作用是將數據轉換為網絡能夠識別和傳輸的格式,例如將數據包封裝成以太網幀,以便在以太網上進行傳輸。同時,網絡適配器也負責監控網絡上的數據流量,並在需要時觸發 IRQ 請求,通知處理器需要處理數據包。

網絡適配器的性能對網絡通信的效率和吞吐量有很大影響。在高性能計算環境中,通常會選擇高速的網絡適配器,例如 10GbE、40GbE、100GbE 等,以滿足大規模數據傳輸的需求。

為什麼在K8S的IQR會比一般Linux主機更明顯

當一般主機傳輸大量流時,也會產生網絡適配器的 IRQ 請求。但是,這種情況下的 IRQ 請求通常可以被系統有效地處理,並不會對 CPU 的負載產生太大的影響。這是因為一般主機的網絡適配器通常採用了更為先進的中斷卸載技術,如 RSS(Receive Side Scaling)、RPS(Receive Packet Steering)等,可以將 IRQ 請求在多個 CPU 核心上進行分配,從而有效地提高系統的網絡吞吐量。

在 Kubernetes 中,由於每個節點上的 Pod 分佈不確定,因此無法像一般主機那樣進行有效的中斷卸載。此外,由於網絡流量是從 NodePort 直接傳輸到 Pod,中間可能還需要經過多個網絡層,從而增加了系統的網絡負載。因此,在高負載情況下,使用 NodePort 公開服務可能會導致大量 IRQ 請求,從而增加 CPU 的負載。為了解決這個問題,可以考慮使用負載均衡器(ingress)等技術,將流量轉發到多個節點上,以降低單個節點的負載。

解決方法

由於我們所架設的伺服器為串流伺服器,原本在一般的Linux主機裡面,我們會使用NGINX去做反向代理,讓主機知道現在的連接目標為串流,如下面這個nginx.conf的範例

http {
    include       mime.types;
    default_type  application/octet-stream; #設定所傳輸的格式為串流
    sendfile        on;
}

這樣子當有人透過http去拉取串流時,NIC就會採取長連接的方式去處理這條串流,但是,因為現在我們將串流伺服器移到K8S裡面去,連線請求處理的地方會在worker node所在的NIC上去處理,而不是在串流服務的POD去處理的。因此,即便我們在POD裡面設定連線方式為串流,在worker node上面也是不知道這件事情的。

所以我們會必須要在K8S的ingress裡面去做進一步的設定,第一步要先了解自己的K8S的ingress是用甚麼實作的,例如像我們的K8S是用kubernetes/ingress-nginx實作的

設定介紹: NGINX Configuration

這邊會有三個方式去實作

  1. ConfigMap:使用 Configmap 在 NGINX 中設置全局配置。
  2. Annotations:如果您想要特定 Ingress 規則的特定配置,請使用它。
  3. 自定義模板:當需要更具體的設置時,如open_file_cache,調整監聽選項,rcvbuf或者當無法通過 ConfigMap 更改配置時。

以下是一個使用 types 設置 MIME 類型的示例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      types {
        text/html                             html htm shtml;
        text/css                              css;
        text/xml                              xml;
        image/gif                             gif;
        image/jpeg                            jpeg jpg;
        application/javascript               js;
        application/atom+xml                  atom;
        application/rss+xml                   rss;
        text/mathml                           mml;
        text/plain                            txt;
        text/vnd.sun.j2me.app-descriptor      jad;
        text/vnd.wap.wml                      wml;
        text/x-component                      htc;
        image/png                             png;
        image/tiff                            tif tiff;
        image/vnd.wap.wbmp                    wbmp;
        image/x-icon                          ico;
        image/x-jng                           jng;
        image/x-ms-bmp                        bmp;
        image/svg+xml                         svg svgz;
        image/webp                            webp;
        application/font-woff                 woff;
        application/font-woff2                woff2;
        application/vnd.ms-fontobject         eot;
        application/x-font-ttf                ttc ttf;
        application/x-httpd-php               php;
        application/x-shockwave-flash         swf;
        application/json                      json;
        application/octet-stream              flv; #這邊可以設定MINE TYPE
      }
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  name: http

這樣子就可以正確的於ingress處理串流的連接了!

相關官方說明: Annotations – Ingress-Nginx ControllerCustom Headers – Ingress-Nginx Controller

Posted on

使用Helm來部署K8S

Helm介紹

Helm 是一個 Kubernetes 包管理器,它可以幫助您在 Kubernetes 上部署和管理應用程序。Helm 允許您定義、安裝和升級 Kubernetes 應用程序,並且可以管理它們的依賴關係。

Helm 由兩部分組成:Helm CLI 和 Helm Charts。Helm CLI 是一個命令行界面,用於管理 Helm Charts。Helm Charts 是一個包含 Kubernetes 资源描述文件的打包文件,例如 Deployment、Service、Ingress、ConfigMap 等等。這些文件被打包到壹個壓縮文件中,通常是 tar.gz 或 zip 格式。

使用 Helm,您可以通過創建自己的 Charts 或者使用社區提供的 Charts 快速部署應用程序。您可以使用 Helm Charts 定義 Kubernetes 资源,然後通過 Helm CLI 安裝 Charts 來創建和管理 Kubernetes 资源。

Helm 還允許您管理 Charts 的版本控制,從而使您可以輕鬆地升級或回滾到先前的版本。此外,Helm 還支持模板化和參數化 Charts,從而使您可以通過使用不同的參數集在不同的環境中部署同一個 Chart。

Helm的安裝

  1. 下載 Helm: 下載頁面有各個作業系統的下載檔案,這邊是官方的安裝指南(Installing Helm)
  2. 解壓 Helm
  3. 將 Helm 的執行文件複製到可執行路徑中,若為linux可能為/usr/local/bin/,若為Window則為C:\Users\my_name
  4. 驗證 Helm 是否正確安裝。運行以下命令應該會顯示 Helm 的版本信息: helm version

Helm的使用指令

這邊是使用的指令碼的介紹: https://helm.sh/docs/intro/using_helm/

創建新的專案可用下面指令

helm install happy-panda bitnami/wordpress

會有類似這樣的資料夾結構

其中Chart.yaml會在創建時設定好,values.yaml可以設定在templates要使用的變數,而templates則是要放我們要部署的YAML設定檔。

接著用下面的指令就可以部署到K8S了!

helm upgrade --install -n stu-srs --set APP_ENV=QAT srs-core1 . --values ./values-core1.yaml --version v1.0.0 
Posted on

Prometheus Exporter: json-exporter

甚麼是JSON Exporter

JSON Exporter是一個Prometheus的exporter(指標收集器),它能夠從提供JSON格式的API中收集指標數據,並將這些數據轉換為Prometheus所支持的格式,以便Prometheus進行分析和視覺化。

JSON Exporter的運行方式是通過設置JSON配置文件,其中包括API端點和相關的指標數據,然後使用Prometheus的配置文件將JSON Exporter添加到Prometheus的targets列表中。

JSON Exporter可以收集各種不同類型的指標數據,例如計數器(counters)、量規(gauges)和直方圖(histograms)等,並可以根據需要對數據進行轉換和聚合。

如何設置Exporter

在官方的Writing exporters文件中,有下面這一段

Each exporter should monitor exactly one instance application, preferably sitting right beside it on the same machine. That means for every HAProxy you run, you run a haproxy_exporter process. For every machine with a Mesos worker, you run the Mesos exporter on it, and another one for the master, if a machine has both.

The theory behind this is that for direct instrumentation this is what you’d be doing, and we’re trying to get as close to that as we can in other layouts. This means that all service discovery is done in Prometheus, not in exporters. This also has the benefit that Prometheus has the target information it needs to allow users probe your service with the blackbox exporter.

這段的意思是說,Exporter盡量和主要的Container放在同一個POD裡面,如下圖:

這樣做主要的原因是可以避免單點失敗,且更符合微服務架構的理念。

實作概要

下面是輸出的JSON檔案的範例

{
  "code": 0,
  "server": "vid-69t27o3",
  "streams": [
    {
      "id": "vid-0diw412",
      "name": "livestream",
      "vhost": "vid-y000397",
      "app": "live",
      "tcUrl": "rtmp://172.16.46.86:1935/live",
      "url": "/live/livestream",
      "live_ms": 1681903514993,
      "clients": 4,
      "frames": 0,
      "send_bytes": 45370,
      "recv_bytes": 34930,
      "kbps": {
        "recv_30s": 0,
        "send_30s": 0
      },
      "publish": {
        "active": false
      },
      "video": null,
      "audio": null
    }
  ]
}

下面是json-exporter的config.yml

modules:
  default:
    metrics:
    - name: server
      path: "{ .server}"

    - name: stream_clients
      type: object
      help: Example of sub-level value scrapes from a json
      path: '{.streams[?(@.name!="")]}'
      labels:
        name: '{.name}' 
      values:
        clients: '{.clients}' 
        send_bytes: '{.send_bytes}'
        recv_bytes: '{.recv_bytes}'
        frames: '{.frames}'
        publish: '{.publish.active}'

    headers:
      X-Dummy: my-test-header

設定要監控的POD的YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/instance: srs-core1
  name: srs-core1
  namespace: stu-srs
spec:
  template:
    metadata:
	  creationTimestamp: null
      labels:
        app.kubernetes.io/instance: srs-core1
	containers:
      ....Other container here
      - image: dev-registry.xycloud.org/ldr/streaming/json-exporter
        imagePullPolicy: IfNotPresent
        name: json-exporter
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
		args: ["--config.file", "/config.yml"]
        volumeMounts:
        - mountPath: /config.yml
          name: json-exporter
          subPath: config.yml
	volumes:  
      - configMap:
          defaultMode: 420
          name: json-exporter
        name: json-exporter

進入該POD的SHELL裡面查看Json-exporter所吐的資料

curl "http://localhost:7979/probe?target=http://127.0.0.1:1985/api/v1/streams/"

可以把資料串到Prometheus了

請參考以下文章

  1. 查看普羅米修斯某的pod內所有的值
  2. 查看普羅米修斯監控目標的exporter資訊
Posted on

HorizontalPodAutoscalers by customize metric

設定擴充的行為,sacle down及up的時候所做的行為,這邊的設定是假如維持300秒都穩定相同狀況,則做HPA縮放,最少維持這種狀態60秒,一次增加1個Pod​

這邊則設定要參考的數值,若是要使用自訂義資料,則describedObject這邊要設定的與我們在Rules裡面設定的一致,target部分則設定每一個pods的目標值為多少​

下面scaleTargetRef的部分則是設定要做HPA的目標是甚麼,有可能是Services,這邊做HPA的目標則為Pod​

apiVersion: autoscaling/v2beta2​
kind: HorizontalPodAutoscaler​
metadata:​
  name: srs-edge​
  namespace: srs3​
spec:​
  behavior:​
    scaleDown:​
      policies:​
      - periodSeconds: 60​
        type: Pods​
        value: 1​
      selectPolicy: Max​
      stabilizationWindowSeconds: 300​
    scaleUp:​
      policies:​
      - periodSeconds: 60​
        type: Pods​
        value: 1​
      selectPolicy: Max​
      stabilizationWindowSeconds: 300​
  maxReplicas: 2​
  metrics:​
  - object:​
      describedObject:​
        apiVersion: v1​
        kind: Service​
        name: eventqueue​
      metric:​
        name: stream_total_clients_by_pod​
      target:​
        type: Value​
        value: 1k​
    type: Object​
  minReplicas: 1​
  scaleTargetRef:​
    apiVersion: apps/v1​
    kind: Deployment​
    name: srs-edge​

stream_total_clients_by_pod是我們的客製化變數,這個變數是來自於普羅米修斯,要把普羅米修斯的變數給k8s使用,請參見
http://claire-chang.com/2022/12/16/prometheus-rule-for-alert/
這邊很重要的是可以看到label裡面有name: eventqueue,在Prometheus Rule裡一定也要加上labels: service: eventqueue
這樣這個值才會可以被輸出給普羅米修斯使用

如下圖:

其他更多的設定值請見: https://docs.openshift.com/container-platform/4.9/nodes/pods/nodes-pods-autoscaling.html​

Posted on

查看普羅米修斯某的POD內所有的值

Prometheus 指令

使用的指令如下:

sum by(__name__)({namespace="default",pod="pod_name", __name__=~".*"})

解釋如下:

  • sum by(__name__) 是一個 Prometheus 查詢語句,用於計算符合指定條件的指標值之和,並根據指標名稱進行分組。
  • {namespace="default",pod_name="my-pod"} 是一個標籤選擇器 (label selector),用來選擇符合條件的 POD。其中,namespace 表示命名空間 (namespace),pod_name 表示 POD 名稱。
  • __name__=~"MEERIC.*" 是一個正則表達式選擇器 (regular expression selector),用於選擇符合特定模式的指標名稱。在本例中,我們使用 ~ 運算符將正則表達式 "MEERIC.*" 用於指標名稱,以找到符合條件的指標。這個正則表達式的意思是:以 MEERIC 開頭的所有指標名稱。
  • __name__ 是一個特殊的標籤 (label),代表指標名稱。使用 sum by 子句時,我們將其作為分組條件之一,以根據指標名稱對指標值進行分組。

設定ServiceMonitor

在可以看到所有的值之後,就可以確認你的ServiceMonitor是否正確,可以來設定ServiceMonitor讓普羅米修斯監控正確的對象

以下為一個簡單的範例

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    app.kubernetes.io/instance: srs-json-exporter
  name: json-exporter
  namespace: stu-dashboard
spec:
  endpoints:
  - interval: 30s
    params:
      module:
      - default
      target:
      - http://127.0.0.1:1985/api/v1/streams/
    path: probe
    port: json-exporter
  jobLabel: jobLabel
  namespaceSelector:
    matchNames:
    - stu-srs
  selector:
    matchLabels:
      app: json-exporter

更多關於ServiceMonitor可用的設定值請見:
https://docs.openshift.com/container-platform/4.9/rest_api/monitoring_apis/servicemonitor-monitoring-coreos-com-v1.html

Posted on

使用kubectl進入某個pod裡的某個container的指令

使用kubectl進入container

若要使用 kubectl 進入某個 pod 裡的某個 container,您可以使用 kubectl exec 命令。以下是一個範例指令:
kubectl exec -it -n –container — /bin/sh
在這裡,請將 <pod_name> 替換為您想要進入的 pod 的名稱,將 <container_name> 替換為您想要進入的 container 的名稱。這個指令會使用 /bin/bash shell 進入 container,如果該 container 沒有 /bin/bash,您可以嘗試使用 /bin/sh 作為替代:

kubectl exec -it -n <namespace> <pod_name> -c <container_name> -- /bin/sh

請注意,這些指令假設您已經成功地安裝並設置了 kubectl,並能夠與 Kubernetes 集群通信。

設定kubectl的方法

要配置 kubectl,您需要一個包含集群連接信息的 kubeconfig 文件。通常,當您使用雲服務提供商(如 GKE、EKS 或 AKS)或 Kubernetes 配置工具(如 kopskubeadm)建立集群時,它們會自動為您生成一個 kubeconfig 文件。

kubeconfig 文件通常位於 ~/.kube/config。您可以使用環境變量 KUBECONFIG 來指定 kubeconfig 文件的位置,例如:
export KUBECONFIG=~/.kube/my-kubeconfig.yaml
Kubeconfig file將內容複製到 ~/.kube/config 位置即可​裡面

下載kubectl 或者Lens

即可於本機​ 對K8S下指令

Posted on

在K8S內node js紀錄log的解決方案

千萬不要使用PM2

PM2是一個在linux裡面管理nodejs程序的好工具,它可以讓nodejs在死掉時自動控制重啟,並可於重啟次數超過時停止重啟
但是由於在K8S之中,這種管理的機制已經交由K8S去管理了,因此,若再於裡面包一層PM2,很容易出問題

可能發生的問題

  • pm2 一開始起來時會依你的參數去試著把 resource 給最大化,所以會一下子把 resource 吃滿,這會讓 k8s 覺得 是不是這個 pod 又很忙了,就馬上又起一個 pod 要來試著接手
  • pm2 會自己重啟 node process : 這會讓 k8s 不知道其實 pod 已經死了,就不會再建新的 pod 來接手

PM2其他功能的替代方案

因為PM2的部分功能與K8S重疊,不推薦使用,那關於PM2另外的文字檔log功能,則有幾種方案可解決

  • container 是吐到 stdout,k8s 的 cri 會寫到 host 上
  • 自己實作log系統

而我們公司由於管K8S的系統的運營部門不處理我們的log的儲存以及打至ELK裡的問題,所以就只能採用第二種方案,以下為我們nodeJS的解決方案log4js

使用nodeJS所推出的log管理系統

https://www.npmjs.com/package/log4js
官方的說明非常簡單好懂,下面為一個基礎使用範例,可每日分檔案,儲存三天

const log4js = require("log4js");
log4js.configure({
    appenders: {
        log: { type: "dateFile", filename: "logs/log.log", pattern: "yyyy-MM-dd", layout: { type: "pattern", pattern: "[%d] %m", }, keepFileExt: true, fileNameSep: "-", numBackups: 3 },
        error: { type: "dateFile", filename: "logs/error.log", pattern: "yyyy-MM-dd", layout: { type: "pattern", pattern: "[%d] %m", }, keepFileExt: true, fileNameSep: "-", numBackups: 3 },
    },
    categories: { default: { appenders: ["log"], level: "debug" }, error: { appenders: ["error"], level: "error" } }
});
var logger = log4js.getLogger();
var logger_error = log4js.getLogger("error");
logger.level = "debug";

exports.log = (...msg) => {
    logger.debug(...msg);
}

exports.error = (...msg) => {
    logger_error.error(...msg);
}
Posted on

在K8S裡為Prometheus增加exporter: 以pushgateway為例

PUSHGATEWAY介紹

Prometheus Pushgateway 的存在是為了允許臨時和批處理作業將其指標公開給 Prometheus。由於這類工作存在的時間可能不夠長,無法被抓取,因此他們可以將指標推送到 Pushgateway。Pushgateway 然後將這些指標公開給 Prometheus。

何時使用 PUSHGATEWAY

我們只建議在某些有限的情況下使用 Pushgateway。盲目地使用 Pushgateway 而不是 Prometheus 通常的 pull 模型來進行一般指標收集時,有幾個陷阱:

  • 當通過單個 Pushgateway 監控多個實例時,Pushgateway 既成為單點故障又成為潛在的瓶頸。
  • up 你失去了普羅米修斯通過指標(在每次抓取時生成)的自動實例健康監控。
  • Pushgateway 永遠不會忘記推送給它的系列,並將它們永遠暴露給 Prometheus,除非這些系列是通過 Pushgateway 的 API 手動刪除的。

instance當作業的多個實例通過標籤或類似物在 Pushgateway 中區分它們的指標時,後一點尤其重要。即使原始實例被重命名或刪除,實例的指標也會保留在 Pushgateway 中。這是因為作為指標緩存的 Pushgateway 的生命週期從根本上獨立於將指標推送給它的進程的生命週期。將此與普羅米修斯通常的拉式監控進行對比:當一個實例消失時(有意或無意),其指標將隨之自動消失。使用 Pushgateway 時,情況並非如此,您現在必須手動刪除任何陳舊的指標或自己自動執行此生命週期同步。

通常,Pushgateway 的唯一有效用例是捕獲服務級批處理作業的結果。“服務級”批處理作業是在語義上與特定機器或作業實例不相關的作業(例如,為整個服務刪除多個用戶的批處理作業)。此類作業的指標不應包含機器或實例標籤,以將特定機器或實例的生命週期與推送的指標分離。這減少了在 Pushgateway 中管理陳舊指標的負擔。

取得pushgateway的image

官方檔案: https://hub.docker.com/r/prom/pushgateway
或在cmd輸入
docker pull prom/pushgateway

建立一個含有pushgateway的pod

為pushgateway寫Deployments

apiVersion: apps/v1​
kind: Deployment​
metadata:​
  labels:​
    app: pushgateway​
  name: pushgateway​
  namespace: default​
spec:​
  replicas: 1​
  template:​
    metadata:​
      labels:​
        app: pushgateway​
    spec:​
      containers:​
      - image: prom/pushgateway
        imagePullPolicy: Always​
        name: pushgateway​
        ports:​
        - containerPort: 9091​
          name: pushgateway​
          protocol: TCP​
      dnsPolicy: ClusterFirst​
      restartPolicy: Always​

為pushgateway的POD產生一個Headless Services​

將Service指到對應的Pod​

接著到同域名的容器打
echo “some_metric 3.14” | curl –data-binary @- http://pushgateway:9091/metrics/job/some_job
然後就可以用下面指令看資料
curl http://pushgateway:9091/metrics